[BACK]Return to nfs_serv.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / nfs

Annotation of src/sys/nfs/nfs_serv.c, Revision 1.54.4.1

1.54.4.1! he          1: /*     $NetBSD$        */
1.16      cgd         2:
1.1       cgd         3: /*
1.15      mycroft     4:  * Copyright (c) 1989, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Rick Macklem at The University of Guelph.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the University of
                     21:  *     California, Berkeley and its contributors.
                     22:  * 4. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  *
1.42      fvdl       38:  *     @(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
1.1       cgd        39:  */
                     40:
                     41: /*
1.23      fvdl       42:  * nfs version 2 and 3 server calls to vnode ops
1.1       cgd        43:  * - these routines generally have 3 phases
                     44:  *   1 - break down and validate rpc request in mbuf list
                     45:  *   2 - do the vnode ops for the request
                     46:  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
                     47:  *   3 - build the rpc reply in an mbuf list
                     48:  *   nb:
                     49:  *     - do not mix the phases, since the nfsm_?? macros can return failures
                     50:  *       on a bad rpc or similar and do not do any vrele() or vput()'s
                     51:  *
                     52:  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
                     53:  *     error number iff error != 0 whereas
                     54:  *     returning an error from the server function implies a fatal error
                     55:  *     such as a badly constructed rpc request that should be dropped without
                     56:  *     a reply.
1.23      fvdl       57:  *     For Version 3, nfsm_reply() does not return for the error case, since
                     58:  *     most version 3 rpcs return more than the status for error cases.
1.1       cgd        59:  */
1.41      mrg        60:
1.10      mycroft    61: #include <sys/param.h>
                     62: #include <sys/systm.h>
                     63: #include <sys/proc.h>
                     64: #include <sys/file.h>
                     65: #include <sys/namei.h>
                     66: #include <sys/vnode.h>
                     67: #include <sys/mount.h>
1.23      fvdl       68: #include <sys/socket.h>
                     69: #include <sys/socketvar.h>
1.10      mycroft    70: #include <sys/mbuf.h>
1.15      mycroft    71: #include <sys/dirent.h>
                     72: #include <sys/stat.h>
1.23      fvdl       73: #include <sys/kernel.h>
                     74: #include <ufs/ufs/dir.h>
1.1       cgd        75:
1.15      mycroft    76: #include <vm/vm.h>
1.1       cgd        77:
1.40      mrg        78: #include <uvm/uvm_extern.h>
                     79:
1.23      fvdl       80: #include <nfs/nfsproto.h>
1.15      mycroft    81: #include <nfs/rpcv2.h>
1.10      mycroft    82: #include <nfs/nfs.h>
                     83: #include <nfs/xdr_subs.h>
                     84: #include <nfs/nfsm_subs.h>
1.15      mycroft    85: #include <nfs/nqnfs.h>
1.22      christos   86: #include <nfs/nfs_var.h>
1.1       cgd        87:
                     88: /* Global vars */
1.19      cgd        89: extern u_int32_t nfs_xdrneg1;
                     90: extern u_int32_t nfs_false, nfs_true;
1.23      fvdl       91: extern enum vtype nv3tov_type[8];
                     92: extern struct nfsstats nfsstats;
                     93: extern nfstype nfsv2_type[9];
                     94: extern nfstype nfsv3_type[9];
                     95: int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
1.1       cgd        96:
1.15      mycroft    97: /*
1.23      fvdl       98:  * nfs v3 access service
1.15      mycroft    99:  */
1.22      christos  100: int
1.23      fvdl      101: nfsrv3_access(nfsd, slp, procp, mrq)
                    102:        struct nfsrv_descript *nfsd;
                    103:        struct nfssvc_sock *slp;
                    104:        struct proc *procp;
                    105:        struct mbuf **mrq;
1.15      mycroft   106: {
1.23      fvdl      107:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    108:        struct mbuf *nam = nfsd->nd_nam;
                    109:        caddr_t dpos = nfsd->nd_dpos;
                    110:        struct ucred *cred = &nfsd->nd_cr;
1.15      mycroft   111:        struct vnode *vp;
1.23      fvdl      112:        nfsfh_t nfh;
1.15      mycroft   113:        fhandle_t *fhp;
1.54      augustss  114:        u_int32_t *tl;
                    115:        int32_t t1;
1.15      mycroft   116:        caddr_t bpos;
1.23      fvdl      117:        int error = 0, rdonly, cache = 0, getret;
1.15      mycroft   118:        char *cp2;
1.23      fvdl      119:        struct mbuf *mb, *mreq, *mb2;
                    120:        struct vattr va;
1.32      mycroft   121:        u_long inmode, testmode, outmode;
1.15      mycroft   122:        u_quad_t frev;
                    123:
                    124:        fhp = &nfh.fh_generic;
                    125:        nfsm_srvmtofh(fhp);
1.23      fvdl      126:        nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                    127:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
1.35      fvdl      128:            (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      129:        if (error) {
                    130:                nfsm_reply(NFSX_UNSIGNED);
                    131:                nfsm_srvpostop_attr(1, (struct vattr *)0);
                    132:                return (0);
                    133:        }
1.32      mycroft   134:        inmode = fxdr_unsigned(u_int32_t, *tl);
                    135:        outmode = 0;
                    136:        if ((inmode & NFSV3ACCESS_READ) &&
                    137:            nfsrv_access(vp, VREAD, cred, rdonly, procp, 0) == 0)
                    138:                outmode |= NFSV3ACCESS_READ;
                    139:        if (vp->v_type != VDIR) {
                    140:                testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
                    141:                if (testmode &&
                    142:                    nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
                    143:                        outmode |= testmode;
                    144:                if ((inmode & NFSV3ACCESS_EXECUTE) &&
                    145:                    nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
                    146:                        outmode |= NFSV3ACCESS_EXECUTE;
                    147:        } else {
                    148:                testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
                    149:                    NFSV3ACCESS_DELETE);
                    150:                if (testmode &&
                    151:                    nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
                    152:                        outmode |= testmode;
                    153:                if ((inmode & NFSV3ACCESS_LOOKUP) &&
1.33      mycroft   154:                    nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
1.32      mycroft   155:                        outmode |= NFSV3ACCESS_LOOKUP;
                    156:        }
1.23      fvdl      157:        getret = VOP_GETATTR(vp, &va, cred, procp);
1.15      mycroft   158:        vput(vp);
1.23      fvdl      159:        nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
                    160:        nfsm_srvpostop_attr(getret, &va);
                    161:        nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1.32      mycroft   162:        *tl = txdr_unsigned(outmode);
1.15      mycroft   163:        nfsm_srvdone;
                    164: }
                    165:
1.1       cgd       166: /*
                    167:  * nfs getattr service
                    168:  */
1.22      christos  169: int
1.23      fvdl      170: nfsrv_getattr(nfsd, slp, procp, mrq)
                    171:        struct nfsrv_descript *nfsd;
                    172:        struct nfssvc_sock *slp;
                    173:        struct proc *procp;
                    174:        struct mbuf **mrq;
1.1       cgd       175: {
1.23      fvdl      176:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    177:        struct mbuf *nam = nfsd->nd_nam;
                    178:        caddr_t dpos = nfsd->nd_dpos;
                    179:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  180:        struct nfs_fattr *fp;
1.1       cgd       181:        struct vattr va;
                    182:        struct vnode *vp;
1.23      fvdl      183:        nfsfh_t nfh;
1.1       cgd       184:        fhandle_t *fhp;
1.54      augustss  185:        u_int32_t *tl;
                    186:        int32_t t1;
1.1       cgd       187:        caddr_t bpos;
1.15      mycroft   188:        int error = 0, rdonly, cache;
1.1       cgd       189:        char *cp2;
                    190:        struct mbuf *mb, *mb2, *mreq;
1.15      mycroft   191:        u_quad_t frev;
1.1       cgd       192:
                    193:        fhp = &nfh.fh_generic;
                    194:        nfsm_srvmtofh(fhp);
1.23      fvdl      195:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
1.35      fvdl      196:            (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      197:        if (error) {
1.1       cgd       198:                nfsm_reply(0);
1.23      fvdl      199:                return (0);
                    200:        }
                    201:        nqsrv_getl(vp, ND_READ);
                    202:        error = VOP_GETATTR(vp, &va, cred, procp);
1.1       cgd       203:        vput(vp);
1.23      fvdl      204:        nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
                    205:        if (error)
                    206:                return (0);
                    207:        nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
                    208:        nfsm_srvfillattr(&va, fp);
1.1       cgd       209:        nfsm_srvdone;
                    210: }
                    211:
                    212: /*
                    213:  * nfs setattr service
                    214:  */
1.22      christos  215: int
1.23      fvdl      216: nfsrv_setattr(nfsd, slp, procp, mrq)
                    217:        struct nfsrv_descript *nfsd;
                    218:        struct nfssvc_sock *slp;
                    219:        struct proc *procp;
                    220:        struct mbuf **mrq;
1.1       cgd       221: {
1.23      fvdl      222:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    223:        struct mbuf *nam = nfsd->nd_nam;
                    224:        caddr_t dpos = nfsd->nd_dpos;
                    225:        struct ucred *cred = &nfsd->nd_cr;
                    226:        struct vattr va, preat;
1.54      augustss  227:        struct nfsv2_sattr *sp;
                    228:        struct nfs_fattr *fp;
1.1       cgd       229:        struct vnode *vp;
1.23      fvdl      230:        nfsfh_t nfh;
1.1       cgd       231:        fhandle_t *fhp;
1.54      augustss  232:        u_int32_t *tl;
                    233:        int32_t t1;
1.1       cgd       234:        caddr_t bpos;
1.23      fvdl      235:        int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
                    236:        int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
1.1       cgd       237:        char *cp2;
                    238:        struct mbuf *mb, *mb2, *mreq;
1.23      fvdl      239:        u_quad_t frev;
                    240:        struct timespec guard;
1.1       cgd       241:
                    242:        fhp = &nfh.fh_generic;
                    243:        nfsm_srvmtofh(fhp);
1.18      mycroft   244:        VATTR_NULL(&va);
1.23      fvdl      245:        if (v3) {
                    246:                nfsm_srvsattr(&va);
                    247:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                    248:                gcheck = fxdr_unsigned(int, *tl);
                    249:                if (gcheck) {
                    250:                        nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
                    251:                        fxdr_nfsv3time(tl, &guard);
                    252:                }
                    253:        } else {
                    254:                nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
                    255:                /*
                    256:                 * Nah nah nah nah na nah
                    257:                 * There is a bug in the Sun client that puts 0xffff in the mode
                    258:                 * field of sattr when it should put in 0xffffffff. The u_short
                    259:                 * doesn't sign extend.
                    260:                 * --> check the low order 2 bytes for 0xffff
                    261:                 */
                    262:                if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
                    263:                        va.va_mode = nfstov_mode(sp->sa_mode);
                    264:                if (sp->sa_uid != nfs_xdrneg1)
                    265:                        va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
                    266:                if (sp->sa_gid != nfs_xdrneg1)
                    267:                        va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
                    268:                if (sp->sa_size != nfs_xdrneg1)
                    269:                        va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
                    270:                if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
1.15      mycroft   271: #ifdef notyet
1.23      fvdl      272:                        fxdr_nfsv2time(&sp->sa_atime, &va.va_atime);
1.15      mycroft   273: #else
1.20      jtc       274:                        va.va_atime.tv_sec =
1.23      fvdl      275:                                fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
1.20      jtc       276:                        va.va_atime.tv_nsec = 0;
1.15      mycroft   277: #endif
                    278:                }
1.23      fvdl      279:                if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
                    280:                        fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime);
                    281:
                    282:        }
                    283:
                    284:        /*
                    285:         * Now that we have all the fields, lets do it.
                    286:         */
                    287:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
1.35      fvdl      288:            (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      289:        if (error) {
                    290:                nfsm_reply(2 * NFSX_UNSIGNED);
                    291:                nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
                    292:                return (0);
                    293:        }
                    294:        nqsrv_getl(vp, ND_WRITE);
                    295:        if (v3) {
                    296:                error = preat_ret = VOP_GETATTR(vp, &preat, cred, procp);
                    297:                if (!error && gcheck &&
                    298:                        (preat.va_ctime.tv_sec != guard.tv_sec ||
                    299:                         preat.va_ctime.tv_nsec != guard.tv_nsec))
                    300:                        error = NFSERR_NOT_SYNC;
                    301:                if (error) {
                    302:                        vput(vp);
                    303:                        nfsm_reply(NFSX_WCCDATA(v3));
                    304:                        nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
                    305:                        return (0);
                    306:                }
1.15      mycroft   307:        }
                    308:
1.1       cgd       309:        /*
1.15      mycroft   310:         * If the size is being changed write acces is required, otherwise
                    311:         * just check for a read only file system.
1.1       cgd       312:         */
1.18      mycroft   313:        if (va.va_size == ((u_quad_t)((quad_t) -1))) {
1.15      mycroft   314:                if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
                    315:                        error = EROFS;
                    316:                        goto out;
                    317:                }
                    318:        } else {
                    319:                if (vp->v_type == VDIR) {
                    320:                        error = EISDIR;
                    321:                        goto out;
1.22      christos  322:                } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
1.27      fvdl      323:                        procp, 0)) != 0)
1.15      mycroft   324:                        goto out;
1.1       cgd       325:        }
1.23      fvdl      326:        error = VOP_SETATTR(vp, &va, cred, procp);
                    327:        postat_ret = VOP_GETATTR(vp, &va, cred, procp);
                    328:        if (!error)
                    329:                error = postat_ret;
1.1       cgd       330: out:
                    331:        vput(vp);
1.23      fvdl      332:        nfsm_reply(NFSX_WCCORFATTR(v3));
                    333:        if (v3) {
                    334:                nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
                    335:                return (0);
                    336:        } else {
                    337:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                    338:                nfsm_srvfillattr(&va, fp);
1.15      mycroft   339:        }
1.1       cgd       340:        nfsm_srvdone;
                    341: }
                    342:
                    343: /*
                    344:  * nfs lookup rpc
                    345:  */
1.22      christos  346: int
1.23      fvdl      347: nfsrv_lookup(nfsd, slp, procp, mrq)
                    348:        struct nfsrv_descript *nfsd;
                    349:        struct nfssvc_sock *slp;
                    350:        struct proc *procp;
                    351:        struct mbuf **mrq;
1.1       cgd       352: {
1.23      fvdl      353:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    354:        struct mbuf *nam = nfsd->nd_nam;
                    355:        caddr_t dpos = nfsd->nd_dpos;
                    356:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  357:        struct nfs_fattr *fp;
1.35      fvdl      358:        struct nameidata nd, ind, *ndp = &nd;
1.23      fvdl      359:        struct vnode *vp, *dirp;
                    360:        nfsfh_t nfh;
1.1       cgd       361:        fhandle_t *fhp;
1.54      augustss  362:        caddr_t cp;
                    363:        u_int32_t *tl;
                    364:        int32_t t1;
1.1       cgd       365:        caddr_t bpos;
1.23      fvdl      366:        int error = 0, cache, len, dirattr_ret = 1;
1.35      fvdl      367:        int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
1.1       cgd       368:        char *cp2;
                    369:        struct mbuf *mb, *mb2, *mreq;
1.23      fvdl      370:        struct vattr va, dirattr;
                    371:        u_quad_t frev;
1.1       cgd       372:
                    373:        fhp = &nfh.fh_generic;
                    374:        nfsm_srvmtofh(fhp);
1.23      fvdl      375:        nfsm_srvnamesiz(len);
1.35      fvdl      376:
                    377:        pubflag = nfs_ispublicfh(fhp);
                    378:
1.15      mycroft   379:        nd.ni_cnd.cn_cred = cred;
                    380:        nd.ni_cnd.cn_nameiop = LOOKUP;
                    381:        nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
1.23      fvdl      382:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.35      fvdl      383:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
                    384:
                    385:        if (!error && pubflag) {
                    386:                if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
                    387:                        /*
                    388:                         * Setup call to lookup() to see if we can find
                    389:                         * the index file. Arguably, this doesn't belong
                    390:                         * in a kernel.. Ugh.
                    391:                         */
                    392:                        ind = nd;
1.42      fvdl      393:                        VOP_UNLOCK(nd.ni_vp, 0);
1.35      fvdl      394:                        ind.ni_pathlen = strlen(nfs_pub.np_index);
                    395:                        ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
                    396:                            nfs_pub.np_index;
                    397:                        ind.ni_startdir = nd.ni_vp;
                    398:                        VREF(ind.ni_startdir);
                    399:                        error = lookup(&ind);
                    400:                        if (!error) {
                    401:                                /*
                    402:                                 * Found an index file. Get rid of
                    403:                                 * the old references.
                    404:                                 */
                    405:                                if (dirp)
                    406:                                        vrele(dirp);
                    407:                                dirp = nd.ni_vp;
                    408:                                vrele(nd.ni_startdir);
                    409:                                ndp = &ind;
                    410:                        } else
                    411:                                error = 0;
                    412:                }
                    413:                /*
                    414:                 * If the public filehandle was used, check that this lookup
                    415:                 * didn't result in a filehandle outside the publicly exported
                    416:                 * filesystem.
                    417:                 */
                    418:
                    419:                if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) {
                    420:                        vput(nd.ni_vp);
                    421:                        error = EPERM;
                    422:                }
                    423:        }
                    424:
1.23      fvdl      425:        if (dirp) {
                    426:                if (v3)
                    427:                        dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
                    428:                                procp);
                    429:                vrele(dirp);
                    430:        }
1.35      fvdl      431:
1.23      fvdl      432:        if (error) {
                    433:                nfsm_reply(NFSX_POSTOPATTR(v3));
                    434:                nfsm_srvpostop_attr(dirattr_ret, &dirattr);
                    435:                return (0);
                    436:        }
1.35      fvdl      437:
                    438:        nqsrv_getl(ndp->ni_startdir, ND_READ);
                    439:        vrele(ndp->ni_startdir);
1.15      mycroft   440:        FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
1.35      fvdl      441:        vp = ndp->ni_vp;
1.44      perry     442:        memset((caddr_t)fhp, 0, sizeof(nfh));
1.1       cgd       443:        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1.23      fvdl      444:        error = VFS_VPTOFH(vp, &fhp->fh_fid);
                    445:        if (!error)
                    446:                error = VOP_GETATTR(vp, &va, cred, procp);
                    447:        vput(vp);
                    448:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
                    449:        if (error) {
                    450:                nfsm_srvpostop_attr(dirattr_ret, &dirattr);
                    451:                return (0);
1.1       cgd       452:        }
1.23      fvdl      453:        nfsm_srvfhtom(fhp, v3);
                    454:        if (v3) {
                    455:                nfsm_srvpostop_attr(0, &va);
                    456:                nfsm_srvpostop_attr(dirattr_ret, &dirattr);
                    457:        } else {
                    458:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                    459:                nfsm_srvfillattr(&va, fp);
1.15      mycroft   460:        }
1.1       cgd       461:        nfsm_srvdone;
                    462: }
                    463:
                    464: /*
                    465:  * nfs readlink service
                    466:  */
1.22      christos  467: int
1.23      fvdl      468: nfsrv_readlink(nfsd, slp, procp, mrq)
                    469:        struct nfsrv_descript *nfsd;
                    470:        struct nfssvc_sock *slp;
                    471:        struct proc *procp;
                    472:        struct mbuf **mrq;
1.1       cgd       473: {
1.23      fvdl      474:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    475:        struct mbuf *nam = nfsd->nd_nam;
                    476:        caddr_t dpos = nfsd->nd_dpos;
                    477:        struct ucred *cred = &nfsd->nd_cr;
1.1       cgd       478:        struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
1.54      augustss  479:        struct iovec *ivp = iv;
                    480:        struct mbuf *mp;
                    481:        u_int32_t *tl;
                    482:        int32_t t1;
1.1       cgd       483:        caddr_t bpos;
1.23      fvdl      484:        int error = 0, rdonly, cache, i, tlen, len, getret;
                    485:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd       486:        char *cp2;
1.22      christos  487:        struct mbuf *mb, *mb2, *mp2 = NULL, *mp3 = NULL, *mreq;
1.1       cgd       488:        struct vnode *vp;
1.23      fvdl      489:        struct vattr attr;
                    490:        nfsfh_t nfh;
1.1       cgd       491:        fhandle_t *fhp;
                    492:        struct uio io, *uiop = &io;
1.15      mycroft   493:        u_quad_t frev;
1.1       cgd       494:
                    495:        fhp = &nfh.fh_generic;
                    496:        nfsm_srvmtofh(fhp);
                    497:        len = 0;
                    498:        i = 0;
                    499:        while (len < NFS_MAXPATHLEN) {
                    500:                MGET(mp, M_WAIT, MT_DATA);
                    501:                MCLGET(mp, M_WAIT);
                    502:                mp->m_len = NFSMSIZ(mp);
                    503:                if (len == 0)
                    504:                        mp3 = mp2 = mp;
                    505:                else {
                    506:                        mp2->m_next = mp;
                    507:                        mp2 = mp;
                    508:                }
                    509:                if ((len+mp->m_len) > NFS_MAXPATHLEN) {
                    510:                        mp->m_len = NFS_MAXPATHLEN-len;
                    511:                        len = NFS_MAXPATHLEN;
                    512:                } else
                    513:                        len += mp->m_len;
                    514:                ivp->iov_base = mtod(mp, caddr_t);
                    515:                ivp->iov_len = mp->m_len;
                    516:                i++;
                    517:                ivp++;
                    518:        }
                    519:        uiop->uio_iov = iv;
                    520:        uiop->uio_iovcnt = i;
                    521:        uiop->uio_offset = 0;
                    522:        uiop->uio_resid = len;
                    523:        uiop->uio_rw = UIO_READ;
                    524:        uiop->uio_segflg = UIO_SYSSPACE;
                    525:        uiop->uio_procp = (struct proc *)0;
1.23      fvdl      526:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl      527:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.22      christos  528:        if (error) {
1.1       cgd       529:                m_freem(mp3);
1.23      fvdl      530:                nfsm_reply(2 * NFSX_UNSIGNED);
                    531:                nfsm_srvpostop_attr(1, (struct vattr *)0);
                    532:                return (0);
1.1       cgd       533:        }
                    534:        if (vp->v_type != VLNK) {
1.23      fvdl      535:                if (v3)
                    536:                        error = EINVAL;
                    537:                else
                    538:                        error = ENXIO;
1.1       cgd       539:                goto out;
                    540:        }
1.23      fvdl      541:        nqsrv_getl(vp, ND_READ);
1.1       cgd       542:        error = VOP_READLINK(vp, uiop, cred);
                    543: out:
1.23      fvdl      544:        getret = VOP_GETATTR(vp, &attr, cred, procp);
1.1       cgd       545:        vput(vp);
                    546:        if (error)
                    547:                m_freem(mp3);
1.23      fvdl      548:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
                    549:        if (v3) {
                    550:                nfsm_srvpostop_attr(getret, &attr);
                    551:                if (error)
                    552:                        return (0);
                    553:        }
1.1       cgd       554:        if (uiop->uio_resid > 0) {
                    555:                len -= uiop->uio_resid;
                    556:                tlen = nfsm_rndup(len);
                    557:                nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
                    558:        }
1.19      cgd       559:        nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1.1       cgd       560:        *tl = txdr_unsigned(len);
                    561:        mb->m_next = mp3;
                    562:        nfsm_srvdone;
                    563: }
                    564:
                    565: /*
                    566:  * nfs read service
                    567:  */
1.22      christos  568: int
1.23      fvdl      569: nfsrv_read(nfsd, slp, procp, mrq)
                    570:        struct nfsrv_descript *nfsd;
                    571:        struct nfssvc_sock *slp;
                    572:        struct proc *procp;
                    573:        struct mbuf **mrq;
1.1       cgd       574: {
1.23      fvdl      575:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    576:        struct mbuf *nam = nfsd->nd_nam;
                    577:        caddr_t dpos = nfsd->nd_dpos;
                    578:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  579:        struct iovec *iv;
1.1       cgd       580:        struct iovec *iv2;
1.54      augustss  581:        struct mbuf *m;
                    582:        struct nfs_fattr *fp;
                    583:        u_int32_t *tl;
                    584:        int32_t t1;
                    585:        int i;
1.1       cgd       586:        caddr_t bpos;
1.23      fvdl      587:        int error = 0, rdonly, cache, cnt, len, left, siz, tlen, getret;
                    588:        int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
1.1       cgd       589:        char *cp2;
                    590:        struct mbuf *mb, *mb2, *mreq;
1.15      mycroft   591:        struct mbuf *m2;
1.1       cgd       592:        struct vnode *vp;
1.23      fvdl      593:        nfsfh_t nfh;
1.1       cgd       594:        fhandle_t *fhp;
                    595:        struct uio io, *uiop = &io;
1.18      mycroft   596:        struct vattr va;
1.1       cgd       597:        off_t off;
1.15      mycroft   598:        u_quad_t frev;
1.1       cgd       599:
                    600:        fhp = &nfh.fh_generic;
                    601:        nfsm_srvmtofh(fhp);
1.23      fvdl      602:        if (v3) {
                    603:                nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.48      fair      604:                off = fxdr_hyper(tl);
1.23      fvdl      605:        } else {
1.19      cgd       606:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                    607:                off = (off_t)fxdr_unsigned(u_int32_t, *tl);
1.15      mycroft   608:        }
1.23      fvdl      609:        nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
                    610:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl      611:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      612:        if (error) {
                    613:                nfsm_reply(2 * NFSX_UNSIGNED);
                    614:                nfsm_srvpostop_attr(1, (struct vattr *)0);
                    615:                return (0);
                    616:        }
1.15      mycroft   617:        if (vp->v_type != VREG) {
1.23      fvdl      618:                if (v3)
                    619:                        error = EINVAL;
                    620:                else
                    621:                        error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1.1       cgd       622:        }
1.23      fvdl      623:        if (!error) {
                    624:            nqsrv_getl(vp, ND_READ);
1.27      fvdl      625:            if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
                    626:                error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
1.23      fvdl      627:        }
                    628:        getret = VOP_GETATTR(vp, &va, cred, procp);
                    629:        if (!error)
                    630:                error = getret;
1.22      christos  631:        if (error) {
1.1       cgd       632:                vput(vp);
1.23      fvdl      633:                nfsm_reply(NFSX_POSTOPATTR(v3));
                    634:                nfsm_srvpostop_attr(getret, &va);
                    635:                return (0);
1.1       cgd       636:        }
1.18      mycroft   637:        if (off >= va.va_size)
1.15      mycroft   638:                cnt = 0;
1.23      fvdl      639:        else if ((off + reqlen) > va.va_size)
1.18      mycroft   640:                cnt = nfsm_rndup(va.va_size - off);
1.23      fvdl      641:        else
                    642:                cnt = reqlen;
                    643:        nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
                    644:        if (v3) {
                    645:                nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
                    646:                *tl++ = nfs_true;
                    647:                fp = (struct nfs_fattr *)tl;
                    648:                tl += (NFSX_V3FATTR / sizeof (u_int32_t));
                    649:        } else {
                    650:                nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
                    651:                fp = (struct nfs_fattr *)tl;
                    652:                tl += (NFSX_V2FATTR / sizeof (u_int32_t));
                    653:        }
1.15      mycroft   654:        len = left = cnt;
                    655:        if (cnt > 0) {
                    656:                /*
                    657:                 * Generate the mbuf list with the uio_iov ref. to it.
                    658:                 */
                    659:                i = 0;
                    660:                m = m2 = mb;
                    661:                while (left > 0) {
                    662:                        siz = min(M_TRAILINGSPACE(m), left);
                    663:                        if (siz > 0) {
1.23      fvdl      664:                                left -= siz;
1.15      mycroft   665:                                i++;
                    666:                        }
                    667:                        if (left > 0) {
                    668:                                MGET(m, M_WAIT, MT_DATA);
                    669:                                MCLGET(m, M_WAIT);
                    670:                                m->m_len = 0;
                    671:                                m2->m_next = m;
                    672:                                m2 = m;
                    673:                        }
                    674:                }
1.23      fvdl      675:                MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
                    676:                       M_TEMP, M_WAITOK);
                    677:                uiop->uio_iov = iv2 = iv;
                    678:                m = mb;
                    679:                left = cnt;
                    680:                i = 0;
                    681:                while (left > 0) {
                    682:                        if (m == NULL)
                    683:                                panic("nfsrv_read iov");
                    684:                        siz = min(M_TRAILINGSPACE(m), left);
                    685:                        if (siz > 0) {
                    686:                                iv->iov_base = mtod(m, caddr_t) + m->m_len;
                    687:                                iv->iov_len = siz;
                    688:                                m->m_len += siz;
                    689:                                left -= siz;
                    690:                                iv++;
                    691:                                i++;
                    692:                        }
                    693:                        m = m->m_next;
                    694:                }
1.15      mycroft   695:                uiop->uio_iovcnt = i;
                    696:                uiop->uio_offset = off;
                    697:                uiop->uio_resid = cnt;
                    698:                uiop->uio_rw = UIO_READ;
                    699:                uiop->uio_segflg = UIO_SYSSPACE;
                    700:                error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
                    701:                off = uiop->uio_offset;
                    702:                FREE((caddr_t)iv2, M_TEMP);
1.23      fvdl      703:                if (error || (getret = VOP_GETATTR(vp, &va, cred, procp)) != 0){
                    704:                        if (!error)
                    705:                                error = getret;
1.15      mycroft   706:                        m_freem(mreq);
                    707:                        vput(vp);
1.23      fvdl      708:                        nfsm_reply(NFSX_POSTOPATTR(v3));
                    709:                        nfsm_srvpostop_attr(getret, &va);
                    710:                        return (0);
1.15      mycroft   711:                }
                    712:        } else
                    713:                uiop->uio_resid = 0;
1.1       cgd       714:        vput(vp);
1.23      fvdl      715:        nfsm_srvfillattr(&va, fp);
1.1       cgd       716:        len -= uiop->uio_resid;
1.15      mycroft   717:        tlen = nfsm_rndup(len);
                    718:        if (cnt != tlen || tlen != len)
1.23      fvdl      719:                nfsm_adj(mb, cnt - tlen, tlen - len);
                    720:        if (v3) {
                    721:                *tl++ = txdr_unsigned(len);
                    722:                if (len < reqlen)
                    723:                        *tl++ = nfs_true;
                    724:                else
                    725:                        *tl++ = nfs_false;
                    726:        }
1.1       cgd       727:        *tl = txdr_unsigned(len);
                    728:        nfsm_srvdone;
                    729: }
                    730:
                    731: /*
                    732:  * nfs write service
                    733:  */
1.22      christos  734: int
1.23      fvdl      735: nfsrv_write(nfsd, slp, procp, mrq)
                    736:        struct nfsrv_descript *nfsd;
                    737:        struct nfssvc_sock *slp;
                    738:        struct proc *procp;
                    739:        struct mbuf **mrq;
1.1       cgd       740: {
1.23      fvdl      741:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    742:        struct mbuf *nam = nfsd->nd_nam;
                    743:        caddr_t dpos = nfsd->nd_dpos;
                    744:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  745:        struct iovec *ivp;
                    746:        int i, cnt;
                    747:        struct mbuf *mp;
                    748:        struct nfs_fattr *fp;
1.23      fvdl      749:        struct iovec *iv;
                    750:        struct vattr va, forat;
1.54      augustss  751:        u_int32_t *tl;
                    752:        int32_t t1;
1.1       cgd       753:        caddr_t bpos;
1.23      fvdl      754:        int error = 0, rdonly, cache, len, forat_ret = 1;
                    755:        int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
                    756:        int stable = NFSV3WRITE_FILESYNC;
                    757:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd       758:        char *cp2;
                    759:        struct mbuf *mb, *mb2, *mreq;
                    760:        struct vnode *vp;
1.23      fvdl      761:        nfsfh_t nfh;
1.1       cgd       762:        fhandle_t *fhp;
                    763:        struct uio io, *uiop = &io;
                    764:        off_t off;
1.15      mycroft   765:        u_quad_t frev;
1.1       cgd       766:
1.23      fvdl      767:        if (mrep == NULL) {
                    768:                *mrq = NULL;
                    769:                return (0);
                    770:        }
1.1       cgd       771:        fhp = &nfh.fh_generic;
                    772:        nfsm_srvmtofh(fhp);
1.23      fvdl      773:        if (v3) {
                    774:                nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1.48      fair      775:                off = fxdr_hyper(tl);
1.23      fvdl      776:                tl += 3;
                    777:                stable = fxdr_unsigned(int, *tl++);
                    778:        } else {
                    779:                nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1.19      cgd       780:                off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1.15      mycroft   781:                tl += 2;
                    782:        }
1.23      fvdl      783:        retlen = len = fxdr_unsigned(int32_t, *tl);
                    784:        cnt = i = 0;
                    785:
                    786:        /*
                    787:         * For NFS Version 2, it is not obvious what a write of zero length
                    788:         * should do, but I might as well be consistent with Version 3,
                    789:         * which is to return ok so long as there are no permission problems.
                    790:         */
                    791:        if (len > 0) {
                    792:            zeroing = 1;
                    793:            mp = mrep;
                    794:            while (mp) {
                    795:                if (mp == md) {
                    796:                        zeroing = 0;
                    797:                        adjust = dpos - mtod(mp, caddr_t);
                    798:                        mp->m_len -= adjust;
                    799:                        if (mp->m_len > 0 && adjust > 0)
                    800:                                NFSMADV(mp, adjust);
                    801:                }
                    802:                if (zeroing)
                    803:                        mp->m_len = 0;
                    804:                else if (mp->m_len > 0) {
                    805:                        i += mp->m_len;
                    806:                        if (i > len) {
                    807:                                mp->m_len -= (i - len);
                    808:                                zeroing = 1;
                    809:                        }
                    810:                        if (mp->m_len > 0)
                    811:                                cnt++;
                    812:                }
                    813:                mp = mp->m_next;
                    814:            }
                    815:        }
                    816:        if (len > NFS_MAXDATA || len < 0 || i < len) {
                    817:                error = EIO;
                    818:                nfsm_reply(2 * NFSX_UNSIGNED);
                    819:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    820:                return (0);
1.1       cgd       821:        }
1.23      fvdl      822:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl      823:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      824:        if (error) {
                    825:                nfsm_reply(2 * NFSX_UNSIGNED);
                    826:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    827:                return (0);
1.1       cgd       828:        }
1.23      fvdl      829:        if (v3)
                    830:                forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
1.15      mycroft   831:        if (vp->v_type != VREG) {
1.23      fvdl      832:                if (v3)
                    833:                        error = EINVAL;
                    834:                else
                    835:                        error = (vp->v_type == VDIR) ? EISDIR : EACCES;
                    836:        }
                    837:        if (!error) {
                    838:                nqsrv_getl(vp, ND_WRITE);
1.27      fvdl      839:                error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
1.15      mycroft   840:        }
1.22      christos  841:        if (error) {
1.1       cgd       842:                vput(vp);
1.23      fvdl      843:                nfsm_reply(NFSX_WCCDATA(v3));
                    844:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    845:                return (0);
                    846:        }
                    847:
                    848:        if (len > 0) {
                    849:            MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
                    850:                M_WAITOK);
                    851:            uiop->uio_iov = iv = ivp;
                    852:            uiop->uio_iovcnt = cnt;
                    853:            mp = mrep;
                    854:            while (mp) {
                    855:                if (mp->m_len > 0) {
                    856:                        ivp->iov_base = mtod(mp, caddr_t);
                    857:                        ivp->iov_len = mp->m_len;
                    858:                        ivp++;
                    859:                }
                    860:                mp = mp->m_next;
                    861:            }
                    862:
                    863:            /*
                    864:             * XXX
                    865:             * The IO_METASYNC flag indicates that all metadata (and not just
                    866:             * enough to ensure data integrity) mus be written to stable storage
                    867:             * synchronously.
                    868:             * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
                    869:             */
                    870:            if (stable == NFSV3WRITE_UNSTABLE)
                    871:                ioflags = IO_NODELOCKED;
                    872:            else if (stable == NFSV3WRITE_DATASYNC)
                    873:                ioflags = (IO_SYNC | IO_NODELOCKED);
                    874:            else
                    875:                ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
                    876:            uiop->uio_resid = len;
                    877:            uiop->uio_rw = UIO_WRITE;
                    878:            uiop->uio_segflg = UIO_SYSSPACE;
                    879:            uiop->uio_procp = (struct proc *)0;
                    880:            uiop->uio_offset = off;
                    881:            error = VOP_WRITE(vp, uiop, ioflags, cred);
                    882:            nfsstats.srvvop_writes++;
                    883:            FREE((caddr_t)iv, M_TEMP);
                    884:        }
                    885:        aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
                    886:        vput(vp);
                    887:        if (!error)
                    888:                error = aftat_ret;
                    889:        nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
                    890:                2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
                    891:        if (v3) {
                    892:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    893:                if (error)
                    894:                        return (0);
                    895:                nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
                    896:                *tl++ = txdr_unsigned(retlen);
                    897:                if (stable == NFSV3WRITE_UNSTABLE)
                    898:                        *tl++ = txdr_unsigned(stable);
                    899:                else
                    900:                        *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
                    901:                /*
                    902:                 * Actually, there is no need to txdr these fields,
                    903:                 * but it may make the values more human readable,
                    904:                 * for debugging purposes.
                    905:                 */
                    906:                *tl++ = txdr_unsigned(boottime.tv_sec);
                    907:                *tl = txdr_unsigned(boottime.tv_usec);
                    908:        } else {
                    909:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                    910:                nfsm_srvfillattr(&va, fp);
                    911:        }
                    912:        nfsm_srvdone;
                    913: }
                    914:
                    915: /*
                    916:  * NFS write service with write gathering support. Called when
                    917:  * nfsrvw_procrastinate > 0.
                    918:  * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
                    919:  * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
                    920:  * Jan. 1994.
                    921:  */
                    922: int
                    923: nfsrv_writegather(ndp, slp, procp, mrq)
                    924:        struct nfsrv_descript **ndp;
                    925:        struct nfssvc_sock *slp;
                    926:        struct proc *procp;
                    927:        struct mbuf **mrq;
                    928: {
1.54      augustss  929:        struct iovec *ivp;
                    930:        struct mbuf *mp;
                    931:        struct nfsrv_descript *wp, *nfsd, *owp, *swp;
                    932:        struct nfs_fattr *fp;
                    933:        int i = 0;
1.23      fvdl      934:        struct iovec *iov;
                    935:        struct nfsrvw_delayhash *wpp;
                    936:        struct ucred *cred;
                    937:        struct vattr va, forat;
1.54      augustss  938:        u_int32_t *tl;
                    939:        int32_t t1;
1.23      fvdl      940:        caddr_t bpos, dpos;
                    941:        int error = 0, rdonly, cache, len = 0, forat_ret = 1;
                    942:        int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
                    943:        char *cp2;
                    944:        struct mbuf *mb, *mb2, *mreq, *mrep, *md;
                    945:        struct vnode *vp;
                    946:        struct uio io, *uiop = &io;
                    947:        u_quad_t frev, cur_usec;
                    948:
                    949:        *mrq = NULL;
                    950:        if (*ndp) {
                    951:            nfsd = *ndp;
                    952:            *ndp = NULL;
                    953:            mrep = nfsd->nd_mrep;
                    954:            md = nfsd->nd_md;
                    955:            dpos = nfsd->nd_dpos;
                    956:            cred = &nfsd->nd_cr;
                    957:            v3 = (nfsd->nd_flag & ND_NFSV3);
                    958:            LIST_INIT(&nfsd->nd_coalesce);
                    959:            nfsd->nd_mreq = NULL;
                    960:            nfsd->nd_stable = NFSV3WRITE_FILESYNC;
                    961:            cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
                    962:            nfsd->nd_time = cur_usec + nfsrvw_procrastinate;
                    963:
                    964:            /*
                    965:             * Now, get the write header..
                    966:             */
                    967:            nfsm_srvmtofh(&nfsd->nd_fh);
                    968:            if (v3) {
                    969:                nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1.48      fair      970:                nfsd->nd_off = fxdr_hyper(tl);
1.23      fvdl      971:                tl += 3;
                    972:                nfsd->nd_stable = fxdr_unsigned(int, *tl++);
                    973:            } else {
                    974:                nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
                    975:                nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
                    976:                tl += 2;
                    977:            }
                    978:            len = fxdr_unsigned(int32_t, *tl);
                    979:            nfsd->nd_len = len;
                    980:            nfsd->nd_eoff = nfsd->nd_off + len;
                    981:
                    982:            /*
                    983:             * Trim the header out of the mbuf list and trim off any trailing
                    984:             * junk so that the mbuf list has only the write data.
                    985:             */
                    986:            zeroing = 1;
                    987:            i = 0;
                    988:            mp = mrep;
                    989:            while (mp) {
                    990:                if (mp == md) {
                    991:                    zeroing = 0;
                    992:                    adjust = dpos - mtod(mp, caddr_t);
                    993:                    mp->m_len -= adjust;
                    994:                    if (mp->m_len > 0 && adjust > 0)
                    995:                        NFSMADV(mp, adjust);
                    996:                }
                    997:                if (zeroing)
                    998:                    mp->m_len = 0;
                    999:                else {
                   1000:                    i += mp->m_len;
                   1001:                    if (i > len) {
                   1002:                        mp->m_len -= (i - len);
                   1003:                        zeroing = 1;
                   1004:                    }
                   1005:                }
                   1006:                mp = mp->m_next;
                   1007:            }
                   1008:            if (len > NFS_MAXDATA || len < 0  || i < len) {
                   1009: nfsmout:
                   1010:                m_freem(mrep);
                   1011:                error = EIO;
                   1012:                nfsm_writereply(2 * NFSX_UNSIGNED, v3);
                   1013:                if (v3)
                   1014:                    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                   1015:                nfsd->nd_mreq = mreq;
                   1016:                nfsd->nd_mrep = NULL;
                   1017:                nfsd->nd_time = 0;
                   1018:            }
                   1019:
                   1020:            /*
                   1021:             * Add this entry to the hash and time queues.
                   1022:             */
                   1023:            s = splsoftclock();
                   1024:            owp = NULL;
                   1025:            wp = slp->ns_tq.lh_first;
                   1026:            while (wp && wp->nd_time < nfsd->nd_time) {
                   1027:                owp = wp;
                   1028:                wp = wp->nd_tq.le_next;
                   1029:            }
                   1030:            if (owp) {
                   1031:                LIST_INSERT_AFTER(owp, nfsd, nd_tq);
                   1032:            } else {
                   1033:                LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
                   1034:            }
                   1035:            if (nfsd->nd_mrep) {
                   1036:                wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
                   1037:                owp = NULL;
                   1038:                wp = wpp->lh_first;
                   1039:                while (wp &&
1.44      perry    1040:                    memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1.23      fvdl     1041:                    owp = wp;
                   1042:                    wp = wp->nd_hash.le_next;
                   1043:                }
                   1044:                while (wp && wp->nd_off < nfsd->nd_off &&
1.44      perry    1045:                    !memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1.23      fvdl     1046:                    owp = wp;
                   1047:                    wp = wp->nd_hash.le_next;
                   1048:                }
                   1049:                if (owp) {
                   1050:                    LIST_INSERT_AFTER(owp, nfsd, nd_hash);
                   1051:
                   1052:                    /*
                   1053:                     * Search the hash list for overlapping entries and
                   1054:                     * coalesce.
                   1055:                     */
                   1056:                    for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
                   1057:                        wp = nfsd->nd_hash.le_next;
                   1058:                        if (NFSW_SAMECRED(owp, nfsd))
                   1059:                            nfsrvw_coalesce(owp, nfsd);
                   1060:                    }
                   1061:                } else {
                   1062:                    LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
                   1063:                }
                   1064:            }
                   1065:            splx(s);
1.1       cgd      1066:        }
1.23      fvdl     1067:
1.1       cgd      1068:        /*
1.23      fvdl     1069:         * Now, do VOP_WRITE()s for any one(s) that need to be done now
                   1070:         * and generate the associated reply mbuf list(s).
1.1       cgd      1071:         */
1.23      fvdl     1072: loop1:
                   1073:        cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
                   1074:        s = splsoftclock();
                   1075:        for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = owp) {
                   1076:                owp = nfsd->nd_tq.le_next;
                   1077:                if (nfsd->nd_time > cur_usec)
                   1078:                    break;
                   1079:                if (nfsd->nd_mreq)
                   1080:                    continue;
                   1081:                LIST_REMOVE(nfsd, nd_tq);
                   1082:                LIST_REMOVE(nfsd, nd_hash);
                   1083:                splx(s);
                   1084:                mrep = nfsd->nd_mrep;
                   1085:                nfsd->nd_mrep = NULL;
                   1086:                cred = &nfsd->nd_cr;
                   1087:                v3 = (nfsd->nd_flag & ND_NFSV3);
                   1088:                forat_ret = aftat_ret = 1;
                   1089:                error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1.35      fvdl     1090:                    nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH),
                   1091:                    FALSE);
1.23      fvdl     1092:                if (!error) {
                   1093:                    if (v3)
                   1094:                        forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
                   1095:                    if (vp->v_type != VREG) {
                   1096:                        if (v3)
                   1097:                            error = EINVAL;
1.1       cgd      1098:                        else
1.23      fvdl     1099:                            error = (vp->v_type == VDIR) ? EISDIR : EACCES;
                   1100:                    }
                   1101:                } else
                   1102:                    vp = NULL;
                   1103:                if (!error) {
                   1104:                    nqsrv_getl(vp, ND_WRITE);
1.27      fvdl     1105:                    error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
1.23      fvdl     1106:                }
                   1107:
                   1108:                if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
                   1109:                    ioflags = IO_NODELOCKED;
                   1110:                else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
                   1111:                    ioflags = (IO_SYNC | IO_NODELOCKED);
                   1112:                else
                   1113:                    ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
                   1114:                uiop->uio_rw = UIO_WRITE;
                   1115:                uiop->uio_segflg = UIO_SYSSPACE;
                   1116:                uiop->uio_procp = (struct proc *)0;
                   1117:                uiop->uio_offset = nfsd->nd_off;
                   1118:                uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
                   1119:                if (uiop->uio_resid > 0) {
                   1120:                    mp = mrep;
                   1121:                    i = 0;
                   1122:                    while (mp) {
                   1123:                        if (mp->m_len > 0)
                   1124:                            i++;
                   1125:                        mp = mp->m_next;
                   1126:                    }
                   1127:                    uiop->uio_iovcnt = i;
                   1128:                    MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
                   1129:                        M_TEMP, M_WAITOK);
                   1130:                    uiop->uio_iov = ivp = iov;
                   1131:                    mp = mrep;
                   1132:                    while (mp) {
                   1133:                        if (mp->m_len > 0) {
                   1134:                            ivp->iov_base = mtod(mp, caddr_t);
                   1135:                            ivp->iov_len = mp->m_len;
                   1136:                            ivp++;
                   1137:                        }
1.1       cgd      1138:                        mp = mp->m_next;
1.23      fvdl     1139:                    }
                   1140:                    if (!error) {
                   1141:                        error = VOP_WRITE(vp, uiop, ioflags, cred);
                   1142:                        nfsstats.srvvop_writes++;
                   1143:                    }
                   1144:                    FREE((caddr_t)iov, M_TEMP);
1.1       cgd      1145:                }
1.23      fvdl     1146:                m_freem(mrep);
                   1147:                if (vp) {
                   1148:                    aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
                   1149:                    vput(vp);
1.1       cgd      1150:                }
1.23      fvdl     1151:
                   1152:                /*
                   1153:                 * Loop around generating replies for all write rpcs that have
                   1154:                 * now been completed.
                   1155:                 */
                   1156:                swp = nfsd;
                   1157:                do {
                   1158:                    if (error) {
                   1159:                        nfsm_writereply(NFSX_WCCDATA(v3), v3);
                   1160:                        if (v3) {
                   1161:                            nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                   1162:                        }
                   1163:                    } else {
                   1164:                        nfsm_writereply(NFSX_PREOPATTR(v3) +
                   1165:                            NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
                   1166:                            NFSX_WRITEVERF(v3), v3);
                   1167:                        if (v3) {
                   1168:                            nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                   1169:                            nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
                   1170:                            *tl++ = txdr_unsigned(nfsd->nd_len);
                   1171:                            *tl++ = txdr_unsigned(swp->nd_stable);
                   1172:                            /*
                   1173:                             * Actually, there is no need to txdr these fields,
                   1174:                             * but it may make the values more human readable,
                   1175:                             * for debugging purposes.
                   1176:                             */
                   1177:                            *tl++ = txdr_unsigned(boottime.tv_sec);
                   1178:                            *tl = txdr_unsigned(boottime.tv_usec);
                   1179:                        } else {
                   1180:                            nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                   1181:                            nfsm_srvfillattr(&va, fp);
                   1182:                        }
                   1183:                    }
                   1184:                    nfsd->nd_mreq = mreq;
                   1185:                    if (nfsd->nd_mrep)
                   1186:                        panic("nfsrv_write: nd_mrep not free");
                   1187:
                   1188:                    /*
                   1189:                     * Done. Put it at the head of the timer queue so that
                   1190:                     * the final phase can return the reply.
                   1191:                     */
                   1192:                    s = splsoftclock();
                   1193:                    if (nfsd != swp) {
                   1194:                        nfsd->nd_time = 0;
                   1195:                        LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
                   1196:                    }
                   1197:                    nfsd = swp->nd_coalesce.lh_first;
                   1198:                    if (nfsd) {
                   1199:                        LIST_REMOVE(nfsd, nd_tq);
                   1200:                    }
                   1201:                    splx(s);
                   1202:                } while (nfsd);
                   1203:                s = splsoftclock();
                   1204:                swp->nd_time = 0;
                   1205:                LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
                   1206:                splx(s);
                   1207:                goto loop1;
                   1208:        }
                   1209:        splx(s);
                   1210:
                   1211:        /*
                   1212:         * Search for a reply to return.
                   1213:         */
                   1214:        s = splsoftclock();
                   1215:        for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = nfsd->nd_tq.le_next)
                   1216:                if (nfsd->nd_mreq) {
                   1217:                    LIST_REMOVE(nfsd, nd_tq);
                   1218:                    *mrq = nfsd->nd_mreq;
                   1219:                    *ndp = nfsd;
                   1220:                    break;
1.1       cgd      1221:                }
1.23      fvdl     1222:        splx(s);
                   1223:        return (0);
                   1224: }
                   1225:
                   1226: /*
                   1227:  * Coalesce the write request nfsd into owp. To do this we must:
                   1228:  * - remove nfsd from the queues
                   1229:  * - merge nfsd->nd_mrep into owp->nd_mrep
                   1230:  * - update the nd_eoff and nd_stable for owp
                   1231:  * - put nfsd on owp's nd_coalesce list
                   1232:  * NB: Must be called at splsoftclock().
                   1233:  */
                   1234: void
                   1235: nfsrvw_coalesce(owp, nfsd)
1.54      augustss 1236:         struct nfsrv_descript *owp;
                   1237:         struct nfsrv_descript *nfsd;
1.23      fvdl     1238: {
1.54      augustss 1239:         int overlap;
                   1240:         struct mbuf *mp;
1.23      fvdl     1241:
                   1242:         LIST_REMOVE(nfsd, nd_hash);
                   1243:         LIST_REMOVE(nfsd, nd_tq);
                   1244:         if (owp->nd_eoff < nfsd->nd_eoff) {
                   1245:             overlap = owp->nd_eoff - nfsd->nd_off;
                   1246:             if (overlap < 0)
                   1247:                 panic("nfsrv_coalesce: bad off");
                   1248:             if (overlap > 0)
                   1249:                 m_adj(nfsd->nd_mrep, overlap);
                   1250:             mp = owp->nd_mrep;
                   1251:             while (mp->m_next)
                   1252:                 mp = mp->m_next;
                   1253:             mp->m_next = nfsd->nd_mrep;
                   1254:             owp->nd_eoff = nfsd->nd_eoff;
                   1255:         } else
                   1256:             m_freem(nfsd->nd_mrep);
                   1257:         nfsd->nd_mrep = NULL;
                   1258:         if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
                   1259:             owp->nd_stable = NFSV3WRITE_FILESYNC;
                   1260:         else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
                   1261:             owp->nd_stable == NFSV3WRITE_UNSTABLE)
                   1262:             owp->nd_stable = NFSV3WRITE_DATASYNC;
                   1263:         LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1.34      fvdl     1264:        /*
                   1265:         * nfsd might hold coalesce elements! Move them to owp.
                   1266:         * Otherwise, requests may be lost and clients will be stuck.
                   1267:         */
                   1268:        if (nfsd->nd_coalesce.lh_first)
                   1269:        {
1.54      augustss 1270:                struct nfsrv_descript *m;
1.34      fvdl     1271:
                   1272:                while ((m = nfsd->nd_coalesce.lh_first))
                   1273:                {
                   1274:                        LIST_REMOVE(m, nd_tq);
                   1275:                        LIST_INSERT_HEAD(&owp->nd_coalesce, m, nd_tq);
                   1276:                }
                   1277:        }
1.1       cgd      1278: }
                   1279:
                   1280: /*
                   1281:  * nfs create service
1.15      mycroft  1282:  * now does a truncate to 0 length via. setattr if it already exists
1.1       cgd      1283:  */
1.22      christos 1284: int
1.23      fvdl     1285: nfsrv_create(nfsd, slp, procp, mrq)
                   1286:        struct nfsrv_descript *nfsd;
                   1287:        struct nfssvc_sock *slp;
                   1288:        struct proc *procp;
                   1289:        struct mbuf **mrq;
1.1       cgd      1290: {
1.23      fvdl     1291:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1292:        struct mbuf *nam = nfsd->nd_nam;
                   1293:        caddr_t dpos = nfsd->nd_dpos;
                   1294:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 1295:        struct nfs_fattr *fp;
1.23      fvdl     1296:        struct vattr va, dirfor, diraft;
1.54      augustss 1297:        struct nfsv2_sattr *sp;
                   1298:        u_int32_t *tl;
1.1       cgd      1299:        struct nameidata nd;
1.54      augustss 1300:        caddr_t cp;
                   1301:        int32_t t1;
1.1       cgd      1302:        caddr_t bpos;
1.23      fvdl     1303:        int error = 0, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
                   1304:        int rdev = 0;
                   1305:        int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1.1       cgd      1306:        char *cp2;
                   1307:        struct mbuf *mb, *mb2, *mreq;
1.23      fvdl     1308:        struct vnode *vp = NULL, *dirp = NULL;
                   1309:        nfsfh_t nfh;
1.1       cgd      1310:        fhandle_t *fhp;
1.23      fvdl     1311:        u_quad_t frev, tempsize;
                   1312:        u_char cverf[NFSX_V3CREATEVERF];
1.1       cgd      1313:
1.15      mycroft  1314:        nd.ni_cnd.cn_nameiop = 0;
1.1       cgd      1315:        fhp = &nfh.fh_generic;
                   1316:        nfsm_srvmtofh(fhp);
1.23      fvdl     1317:        nfsm_srvnamesiz(len);
1.15      mycroft  1318:        nd.ni_cnd.cn_cred = cred;
                   1319:        nd.ni_cnd.cn_nameiop = CREATE;
                   1320:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
1.23      fvdl     1321:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.35      fvdl     1322:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1323:        if (dirp) {
                   1324:                if (v3)
                   1325:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   1326:                                procp);
                   1327:                else {
                   1328:                        vrele(dirp);
                   1329:                        dirp = (struct vnode *)0;
                   1330:                }
                   1331:        }
                   1332:        if (error) {
                   1333:                nfsm_reply(NFSX_WCCDATA(v3));
                   1334:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1335:                if (dirp)
                   1336:                        vrele(dirp);
                   1337:                return (0);
                   1338:        }
1.18      mycroft  1339:        VATTR_NULL(&va);
1.23      fvdl     1340:        if (v3) {
                   1341:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                   1342:                how = fxdr_unsigned(int, *tl);
                   1343:                switch (how) {
                   1344:                case NFSV3CREATE_GUARDED:
                   1345:                        if (nd.ni_vp) {
                   1346:                                error = EEXIST;
                   1347:                                break;
                   1348:                        }
                   1349:                case NFSV3CREATE_UNCHECKED:
                   1350:                        nfsm_srvsattr(&va);
                   1351:                        break;
                   1352:                case NFSV3CREATE_EXCLUSIVE:
                   1353:                        nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
1.44      perry    1354:                        memcpy(cverf, cp, NFSX_V3CREATEVERF);
1.23      fvdl     1355:                        exclusive_flag = 1;
                   1356:                        if (nd.ni_vp == NULL)
                   1357:                                va.va_mode = 0;
                   1358:                        break;
                   1359:                };
                   1360:                va.va_type = VREG;
                   1361:        } else {
                   1362:                nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
                   1363:                va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
                   1364:                if (va.va_type == VNON)
                   1365:                        va.va_type = VREG;
                   1366:                va.va_mode = nfstov_mode(sp->sa_mode);
                   1367:                switch (va.va_type) {
                   1368:                case VREG:
                   1369:                        tsize = fxdr_unsigned(int32_t, sp->sa_size);
                   1370:                        if (tsize != -1)
                   1371:                                va.va_size = (u_quad_t)tsize;
                   1372:                        break;
                   1373:                case VCHR:
                   1374:                case VBLK:
                   1375:                case VFIFO:
                   1376:                        rdev = fxdr_unsigned(int32_t, sp->sa_size);
                   1377:                        break;
                   1378:                default:
                   1379:                        break;
                   1380:                };
                   1381:        }
                   1382:
1.1       cgd      1383:        /*
1.15      mycroft  1384:         * Iff doesn't exist, create it
                   1385:         * otherwise just truncate to 0 length
1.1       cgd      1386:         *   should I set the mode too ??
                   1387:         */
                   1388:        if (nd.ni_vp == NULL) {
1.18      mycroft  1389:                if (va.va_type == VREG || va.va_type == VSOCK) {
1.1       cgd      1390:                        vrele(nd.ni_startdir);
1.23      fvdl     1391:                        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1392:                        error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   1393:                        if (!error) {
                   1394:                                FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1395:                                if (exclusive_flag) {
                   1396:                                        exclusive_flag = 0;
                   1397:                                        VATTR_NULL(&va);
1.44      perry    1398:                                        memcpy((caddr_t)&va.va_atime, cverf,
1.23      fvdl     1399:                                                NFSX_V3CREATEVERF);
                   1400:                                        error = VOP_SETATTR(nd.ni_vp, &va, cred,
                   1401:                                                procp);
                   1402:                                }
                   1403:                        }
1.18      mycroft  1404:                } else if (va.va_type == VCHR || va.va_type == VBLK ||
                   1405:                        va.va_type == VFIFO) {
                   1406:                        if (va.va_type == VCHR && rdev == 0xffffffff)
                   1407:                                va.va_type = VFIFO;
1.46      mrg      1408:                        if (va.va_type != VFIFO &&
                   1409:                            (error = suser(cred, (u_short *)0))) {
1.23      fvdl     1410:                                vrele(nd.ni_startdir);
                   1411:                                free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
1.15      mycroft  1412:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1413:                                vput(nd.ni_dvp);
1.23      fvdl     1414:                                nfsm_reply(0);
                   1415:                                return (error);
1.1       cgd      1416:                        } else
1.18      mycroft  1417:                                va.va_rdev = (dev_t)rdev;
1.23      fvdl     1418:                        nqsrv_getl(nd.ni_dvp, ND_WRITE);
1.22      christos 1419:                        error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
1.23      fvdl     1420:                            &va);
1.22      christos 1421:                        if (error) {
1.1       cgd      1422:                                vrele(nd.ni_startdir);
                   1423:                                nfsm_reply(0);
                   1424:                        }
1.15      mycroft  1425:                        nd.ni_cnd.cn_nameiop = LOOKUP;
                   1426:                        nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
1.23      fvdl     1427:                        nd.ni_cnd.cn_proc = procp;
                   1428:                        nd.ni_cnd.cn_cred = cred;
1.22      christos 1429:                        if ((error = lookup(&nd)) != 0) {
1.15      mycroft  1430:                                free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
1.1       cgd      1431:                                nfsm_reply(0);
                   1432:                        }
1.15      mycroft  1433:                        FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1434:                        if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1.1       cgd      1435:                                vrele(nd.ni_dvp);
                   1436:                                vput(nd.ni_vp);
1.15      mycroft  1437:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1438:                                error = EINVAL;
                   1439:                                nfsm_reply(0);
                   1440:                        }
                   1441:                } else {
1.23      fvdl     1442:                        vrele(nd.ni_startdir);
                   1443:                        free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
1.15      mycroft  1444:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1445:                        vput(nd.ni_dvp);
                   1446:                        error = ENXIO;
                   1447:                }
                   1448:                vp = nd.ni_vp;
                   1449:        } else {
                   1450:                vrele(nd.ni_startdir);
1.15      mycroft  1451:                free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
1.1       cgd      1452:                vp = nd.ni_vp;
                   1453:                if (nd.ni_dvp == vp)
                   1454:                        vrele(nd.ni_dvp);
                   1455:                else
                   1456:                        vput(nd.ni_dvp);
1.15      mycroft  1457:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.50      mycroft  1458:                if (!error && va.va_size != -1) {
1.22      christos 1459:                        error = nfsrv_access(vp, VWRITE, cred,
1.27      fvdl     1460:                            (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
1.23      fvdl     1461:                        if (!error) {
                   1462:                                nqsrv_getl(vp, ND_WRITE);
                   1463:                                tempsize = va.va_size;
                   1464:                                VATTR_NULL(&va);
                   1465:                                va.va_size = tempsize;
                   1466:                                error = VOP_SETATTR(vp, &va, cred,
                   1467:                                         procp);
1.15      mycroft  1468:                        }
1.1       cgd      1469:                }
1.50      mycroft  1470:                if (error)
                   1471:                        vput(vp);
1.1       cgd      1472:        }
1.23      fvdl     1473:        if (!error) {
1.44      perry    1474:                memset((caddr_t)fhp, 0, sizeof(nfh));
1.23      fvdl     1475:                fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
                   1476:                error = VFS_VPTOFH(vp, &fhp->fh_fid);
                   1477:                if (!error)
                   1478:                        error = VOP_GETATTR(vp, &va, cred, procp);
1.1       cgd      1479:                vput(vp);
                   1480:        }
1.23      fvdl     1481:        if (v3) {
                   1482:                if (exclusive_flag && !error &&
1.44      perry    1483:                        memcmp(cverf, (caddr_t)&va.va_atime, NFSX_V3CREATEVERF))
1.23      fvdl     1484:                        error = EEXIST;
                   1485:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
                   1486:                vrele(dirp);
                   1487:        }
                   1488:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
                   1489:        if (v3) {
                   1490:                if (!error) {
                   1491:                        nfsm_srvpostop_fh(fhp);
                   1492:                        nfsm_srvpostop_attr(0, &va);
                   1493:                }
                   1494:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1495:        } else {
                   1496:                nfsm_srvfhtom(fhp, v3);
                   1497:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                   1498:                nfsm_srvfillattr(&va, fp);
                   1499:        }
                   1500:        return (0);
1.1       cgd      1501: nfsmout:
1.23      fvdl     1502:        if (dirp)
                   1503:                vrele(dirp);
                   1504:        if (nd.ni_cnd.cn_nameiop) {
1.1       cgd      1505:                vrele(nd.ni_startdir);
1.23      fvdl     1506:                free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1507:        }
1.15      mycroft  1508:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1509:        if (nd.ni_dvp == nd.ni_vp)
                   1510:                vrele(nd.ni_dvp);
                   1511:        else
                   1512:                vput(nd.ni_dvp);
                   1513:        if (nd.ni_vp)
                   1514:                vput(nd.ni_vp);
                   1515:        return (error);
1.23      fvdl     1516: }
                   1517:
                   1518: /*
                   1519:  * nfs v3 mknod service
                   1520:  */
                   1521: int
                   1522: nfsrv_mknod(nfsd, slp, procp, mrq)
                   1523:        struct nfsrv_descript *nfsd;
                   1524:        struct nfssvc_sock *slp;
                   1525:        struct proc *procp;
                   1526:        struct mbuf **mrq;
                   1527: {
                   1528:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1529:        struct mbuf *nam = nfsd->nd_nam;
                   1530:        caddr_t dpos = nfsd->nd_dpos;
                   1531:        struct ucred *cred = &nfsd->nd_cr;
                   1532:        struct vattr va, dirfor, diraft;
1.54      augustss 1533:        u_int32_t *tl;
1.23      fvdl     1534:        struct nameidata nd;
1.54      augustss 1535:        int32_t t1;
1.23      fvdl     1536:        caddr_t bpos;
                   1537:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   1538:        u_int32_t major, minor;
                   1539:        enum vtype vtyp;
                   1540:        char *cp2;
                   1541:        struct mbuf *mb, *mb2, *mreq;
                   1542:        struct vnode *vp, *dirp = (struct vnode *)0;
                   1543:        nfsfh_t nfh;
                   1544:        fhandle_t *fhp;
                   1545:        u_quad_t frev;
                   1546:
                   1547:        nd.ni_cnd.cn_nameiop = 0;
                   1548:        fhp = &nfh.fh_generic;
                   1549:        nfsm_srvmtofh(fhp);
                   1550:        nfsm_srvnamesiz(len);
                   1551:        nd.ni_cnd.cn_cred = cred;
                   1552:        nd.ni_cnd.cn_nameiop = CREATE;
                   1553:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
                   1554:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.35      fvdl     1555:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1556:        if (dirp)
                   1557:                dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
                   1558:        if (error) {
                   1559:                nfsm_reply(NFSX_WCCDATA(1));
                   1560:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1561:                if (dirp)
                   1562:                        vrele(dirp);
                   1563:                return (0);
                   1564:        }
                   1565:        nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                   1566:        vtyp = nfsv3tov_type(*tl);
                   1567:        if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
                   1568:                vrele(nd.ni_startdir);
                   1569:                free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1570:                error = NFSERR_BADTYPE;
                   1571:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.51      sommerfe 1572:                if (nd.ni_dvp == nd.ni_vp)
                   1573:                        vrele(nd.ni_dvp);
                   1574:                else
                   1575:                        vput(nd.ni_dvp);
                   1576:                if (nd.ni_vp)
                   1577:                        vput(nd.ni_vp);
1.23      fvdl     1578:                goto out;
                   1579:        }
                   1580:        VATTR_NULL(&va);
                   1581:        nfsm_srvsattr(&va);
                   1582:        if (vtyp == VCHR || vtyp == VBLK) {
                   1583:                nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
                   1584:                major = fxdr_unsigned(u_int32_t, *tl++);
                   1585:                minor = fxdr_unsigned(u_int32_t, *tl);
                   1586:                va.va_rdev = makedev(major, minor);
                   1587:        }
1.1       cgd      1588:
1.23      fvdl     1589:        /*
                   1590:         * Iff doesn't exist, create it.
                   1591:         */
                   1592:        if (nd.ni_vp) {
                   1593:                vrele(nd.ni_startdir);
                   1594:                free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1595:                error = EEXIST;
                   1596:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.51      sommerfe 1597:                if (nd.ni_dvp == nd.ni_vp)
                   1598:                        vrele(nd.ni_dvp);
                   1599:                else
                   1600:                        vput(nd.ni_dvp);
                   1601:                vput(nd.ni_vp);
1.23      fvdl     1602:                goto out;
                   1603:        }
                   1604:        va.va_type = vtyp;
                   1605:        if (vtyp == VSOCK) {
                   1606:                vrele(nd.ni_startdir);
                   1607:                nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1608:                error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   1609:                if (!error)
                   1610:                        FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1611:        } else {
1.46      mrg      1612:                if (va.va_type != VFIFO &&
                   1613:                    (error = suser(cred, (u_short *)0))) {
1.23      fvdl     1614:                        vrele(nd.ni_startdir);
                   1615:                        free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1616:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1617:                        vput(nd.ni_dvp);
                   1618:                        goto out;
                   1619:                }
                   1620:                nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1621:                error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   1622:                if (error) {
                   1623:                        vrele(nd.ni_startdir);
                   1624:                        goto out;
                   1625:                }
                   1626:                nd.ni_cnd.cn_nameiop = LOOKUP;
                   1627:                nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
                   1628:                nd.ni_cnd.cn_proc = procp;
                   1629:                nd.ni_cnd.cn_cred = procp->p_ucred;
                   1630:                error = lookup(&nd);
                   1631:                FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1632:                if (error)
                   1633:                        goto out;
                   1634:                if (nd.ni_cnd.cn_flags & ISSYMLINK) {
                   1635:                        vrele(nd.ni_dvp);
                   1636:                        vput(nd.ni_vp);
                   1637:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1638:                        error = EINVAL;
                   1639:                }
                   1640:        }
1.1       cgd      1641: out:
1.23      fvdl     1642:        vp = nd.ni_vp;
                   1643:        if (!error) {
1.44      perry    1644:                memset((caddr_t)fhp, 0, sizeof(nfh));
1.23      fvdl     1645:                fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
                   1646:                error = VFS_VPTOFH(vp, &fhp->fh_fid);
                   1647:                if (!error)
                   1648:                        error = VOP_GETATTR(vp, &va, cred, procp);
                   1649:                vput(vp);
                   1650:        }
                   1651:        diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
                   1652:        vrele(dirp);
                   1653:        nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
                   1654:        if (!error) {
                   1655:                nfsm_srvpostop_fh(fhp);
                   1656:                nfsm_srvpostop_attr(0, &va);
                   1657:        }
                   1658:        nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1659:        return (0);
                   1660: nfsmout:
                   1661:        if (dirp)
                   1662:                vrele(dirp);
                   1663:        if (nd.ni_cnd.cn_nameiop) {
                   1664:                vrele(nd.ni_startdir);
                   1665:                free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1666:        }
                   1667:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1668:        if (nd.ni_dvp == nd.ni_vp)
                   1669:                vrele(nd.ni_dvp);
                   1670:        else
                   1671:                vput(nd.ni_dvp);
                   1672:        if (nd.ni_vp)
                   1673:                vput(nd.ni_vp);
                   1674:        return (error);
1.1       cgd      1675: }
                   1676:
                   1677: /*
                   1678:  * nfs remove service
                   1679:  */
1.22      christos 1680: int
1.23      fvdl     1681: nfsrv_remove(nfsd, slp, procp, mrq)
                   1682:        struct nfsrv_descript *nfsd;
                   1683:        struct nfssvc_sock *slp;
                   1684:        struct proc *procp;
                   1685:        struct mbuf **mrq;
1.1       cgd      1686: {
1.23      fvdl     1687:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1688:        struct mbuf *nam = nfsd->nd_nam;
                   1689:        caddr_t dpos = nfsd->nd_dpos;
                   1690:        struct ucred *cred = &nfsd->nd_cr;
1.1       cgd      1691:        struct nameidata nd;
1.54      augustss 1692:        u_int32_t *tl;
                   1693:        int32_t t1;
1.1       cgd      1694:        caddr_t bpos;
1.23      fvdl     1695:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   1696:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      1697:        char *cp2;
                   1698:        struct mbuf *mb, *mreq;
1.23      fvdl     1699:        struct vnode *vp, *dirp;
                   1700:        struct vattr dirfor, diraft;
                   1701:        nfsfh_t nfh;
1.1       cgd      1702:        fhandle_t *fhp;
1.15      mycroft  1703:        u_quad_t frev;
1.1       cgd      1704:
1.23      fvdl     1705: #ifndef nolint
                   1706:        vp = (struct vnode *)0;
                   1707: #endif
1.1       cgd      1708:        fhp = &nfh.fh_generic;
                   1709:        nfsm_srvmtofh(fhp);
1.23      fvdl     1710:        nfsm_srvnamesiz(len);
1.15      mycroft  1711:        nd.ni_cnd.cn_cred = cred;
                   1712:        nd.ni_cnd.cn_nameiop = DELETE;
                   1713:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1.23      fvdl     1714:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.35      fvdl     1715:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1716:        if (dirp) {
                   1717:                if (v3)
                   1718:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   1719:                                procp);
1.1       cgd      1720:                else
1.23      fvdl     1721:                        vrele(dirp);
1.1       cgd      1722:        }
1.23      fvdl     1723:        if (!error) {
                   1724:                vp = nd.ni_vp;
                   1725:                if (vp->v_type == VDIR &&
                   1726:                    (error = suser(cred, (u_short *)0)) != 0)
                   1727:                        goto out;
                   1728:                /*
                   1729:                 * The root of a mounted filesystem cannot be deleted.
                   1730:                 */
                   1731:                if (vp->v_flag & VROOT) {
                   1732:                        error = EBUSY;
                   1733:                        goto out;
                   1734:                }
1.21      mycroft  1735: out:
1.23      fvdl     1736:                if (!error) {
1.40      mrg      1737:                        (void)uvm_vnp_uncache(vp);
1.23      fvdl     1738:                        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1739:                        nqsrv_getl(vp, ND_WRITE);
                   1740:                        error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
                   1741:                } else {
                   1742:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1743:                        if (nd.ni_dvp == vp)
                   1744:                                vrele(nd.ni_dvp);
                   1745:                        else
                   1746:                                vput(nd.ni_dvp);
                   1747:                        vput(vp);
                   1748:                }
                   1749:        }
                   1750:        if (dirp && v3) {
                   1751:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
                   1752:                vrele(dirp);
                   1753:        }
                   1754:        nfsm_reply(NFSX_WCCDATA(v3));
                   1755:        if (v3) {
                   1756:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1757:                return (0);
                   1758:        }
1.1       cgd      1759:        nfsm_srvdone;
                   1760: }
                   1761:
                   1762: /*
                   1763:  * nfs rename service
                   1764:  */
1.22      christos 1765: int
1.23      fvdl     1766: nfsrv_rename(nfsd, slp, procp, mrq)
                   1767:        struct nfsrv_descript *nfsd;
                   1768:        struct nfssvc_sock *slp;
                   1769:        struct proc *procp;
                   1770:        struct mbuf **mrq;
1.1       cgd      1771: {
1.23      fvdl     1772:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1773:        struct mbuf *nam = nfsd->nd_nam;
                   1774:        caddr_t dpos = nfsd->nd_dpos;
                   1775:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 1776:        u_int32_t *tl;
                   1777:        int32_t t1;
1.1       cgd      1778:        caddr_t bpos;
1.23      fvdl     1779:        int error = 0, cache, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
                   1780:        int tdirfor_ret = 1, tdiraft_ret = 1;
                   1781:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      1782:        char *cp2;
                   1783:        struct mbuf *mb, *mreq;
                   1784:        struct nameidata fromnd, tond;
1.23      fvdl     1785:        struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
                   1786:        struct vnode *tdirp = (struct vnode *)0;
                   1787:        struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
                   1788:        nfsfh_t fnfh, tnfh;
1.1       cgd      1789:        fhandle_t *ffhp, *tfhp;
1.15      mycroft  1790:        u_quad_t frev;
                   1791:        uid_t saved_uid;
1.1       cgd      1792:
1.23      fvdl     1793: #ifndef nolint
                   1794:        fvp = (struct vnode *)0;
                   1795: #endif
1.1       cgd      1796:        ffhp = &fnfh.fh_generic;
                   1797:        tfhp = &tnfh.fh_generic;
1.15      mycroft  1798:        fromnd.ni_cnd.cn_nameiop = 0;
                   1799:        tond.ni_cnd.cn_nameiop = 0;
1.1       cgd      1800:        nfsm_srvmtofh(ffhp);
1.23      fvdl     1801:        nfsm_srvnamesiz(len);
1.1       cgd      1802:        /*
1.15      mycroft  1803:         * Remember our original uid so that we can reset cr_uid before
                   1804:         * the second nfs_namei() call, in case it is remapped.
1.1       cgd      1805:         */
1.15      mycroft  1806:        saved_uid = cred->cr_uid;
                   1807:        fromnd.ni_cnd.cn_cred = cred;
                   1808:        fromnd.ni_cnd.cn_nameiop = DELETE;
                   1809:        fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
1.23      fvdl     1810:        error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
1.35      fvdl     1811:                &dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1812:        if (fdirp) {
                   1813:                if (v3)
                   1814:                        fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
                   1815:                                procp);
                   1816:                else {
                   1817:                        vrele(fdirp);
                   1818:                        fdirp = (struct vnode *)0;
                   1819:                }
                   1820:        }
                   1821:        if (error) {
                   1822:                nfsm_reply(2 * NFSX_WCCDATA(v3));
                   1823:                nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
                   1824:                nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
                   1825:                if (fdirp)
                   1826:                        vrele(fdirp);
                   1827:                return (0);
                   1828:        }
1.1       cgd      1829:        fvp = fromnd.ni_vp;
                   1830:        nfsm_srvmtofh(tfhp);
                   1831:        nfsm_strsiz(len2, NFS_MAXNAMLEN);
1.15      mycroft  1832:        cred->cr_uid = saved_uid;
                   1833:        tond.ni_cnd.cn_cred = cred;
                   1834:        tond.ni_cnd.cn_nameiop = RENAME;
                   1835:        tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
1.23      fvdl     1836:        error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
1.35      fvdl     1837:                &dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1838:        if (tdirp) {
                   1839:                if (v3)
                   1840:                        tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
                   1841:                                procp);
                   1842:                else {
                   1843:                        vrele(tdirp);
                   1844:                        tdirp = (struct vnode *)0;
                   1845:                }
                   1846:        }
1.22      christos 1847:        if (error) {
1.15      mycroft  1848:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1.1       cgd      1849:                vrele(fromnd.ni_dvp);
                   1850:                vrele(fvp);
                   1851:                goto out1;
                   1852:        }
                   1853:        tdvp = tond.ni_dvp;
                   1854:        tvp = tond.ni_vp;
                   1855:        if (tvp != NULL) {
                   1856:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1.23      fvdl     1857:                        if (v3)
                   1858:                                error = EEXIST;
                   1859:                        else
                   1860:                                error = EISDIR;
1.1       cgd      1861:                        goto out;
                   1862:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1.23      fvdl     1863:                        if (v3)
                   1864:                                error = EEXIST;
                   1865:                        else
                   1866:                                error = ENOTDIR;
1.1       cgd      1867:                        goto out;
                   1868:                }
1.15      mycroft  1869:                if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1.23      fvdl     1870:                        if (v3)
                   1871:                                error = EXDEV;
                   1872:                        else
                   1873:                                error = ENOTEMPTY;
1.15      mycroft  1874:                        goto out;
                   1875:                }
                   1876:        }
                   1877:        if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1.23      fvdl     1878:                if (v3)
                   1879:                        error = EXDEV;
                   1880:                else
                   1881:                        error = ENOTEMPTY;
1.15      mycroft  1882:                goto out;
1.1       cgd      1883:        }
                   1884:        if (fvp->v_mount != tdvp->v_mount) {
1.23      fvdl     1885:                if (v3)
                   1886:                        error = EXDEV;
                   1887:                else
                   1888:                        error = ENOTEMPTY;
1.1       cgd      1889:                goto out;
                   1890:        }
1.45      thorpej  1891:        if (fvp == tdvp) {
1.23      fvdl     1892:                if (v3)
                   1893:                        error = EINVAL;
                   1894:                else
                   1895:                        error = ENOTEMPTY;
1.45      thorpej  1896:        }
1.1       cgd      1897:        /*
                   1898:         * If source is the same as the destination (that is the
                   1899:         * same vnode with the same name in the same directory),
                   1900:         * then there is nothing to do.
                   1901:         */
                   1902:        if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1.15      mycroft  1903:            fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1.44      perry    1904:            !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1.15      mycroft  1905:              fromnd.ni_cnd.cn_namelen))
1.1       cgd      1906:                error = -1;
                   1907: out:
                   1908:        if (!error) {
1.23      fvdl     1909:                nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
                   1910:                nqsrv_getl(tdvp, ND_WRITE);
1.30      fvdl     1911:                if (tvp) {
1.40      mrg      1912:                        (void)uvm_vnp_uncache(tvp);
1.23      fvdl     1913:                        nqsrv_getl(tvp, ND_WRITE);
1.30      fvdl     1914:                }
1.15      mycroft  1915:                error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
                   1916:                                   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1.1       cgd      1917:        } else {
1.15      mycroft  1918:                VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1.1       cgd      1919:                if (tdvp == tvp)
                   1920:                        vrele(tdvp);
                   1921:                else
                   1922:                        vput(tdvp);
                   1923:                if (tvp)
                   1924:                        vput(tvp);
1.15      mycroft  1925:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1.1       cgd      1926:                vrele(fromnd.ni_dvp);
                   1927:                vrele(fvp);
1.23      fvdl     1928:                if (error == -1)
                   1929:                        error = 0;
1.1       cgd      1930:        }
                   1931:        vrele(tond.ni_startdir);
1.15      mycroft  1932:        FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1.1       cgd      1933: out1:
1.23      fvdl     1934:        if (fdirp) {
                   1935:                fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp);
                   1936:                vrele(fdirp);
                   1937:        }
                   1938:        if (tdirp) {
                   1939:                tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp);
                   1940:                vrele(tdirp);
                   1941:        }
1.1       cgd      1942:        vrele(fromnd.ni_startdir);
1.15      mycroft  1943:        FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1.23      fvdl     1944:        nfsm_reply(2 * NFSX_WCCDATA(v3));
                   1945:        if (v3) {
                   1946:                nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
                   1947:                nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
                   1948:        }
                   1949:        return (0);
1.1       cgd      1950:
                   1951: nfsmout:
1.23      fvdl     1952:        if (fdirp)
                   1953:                vrele(fdirp);
                   1954:        if (tdirp)
                   1955:                vrele(tdirp);
                   1956:        if (tond.ni_cnd.cn_nameiop) {
1.1       cgd      1957:                vrele(tond.ni_startdir);
1.15      mycroft  1958:                FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1.1       cgd      1959:        }
1.23      fvdl     1960:        if (fromnd.ni_cnd.cn_nameiop) {
1.1       cgd      1961:                vrele(fromnd.ni_startdir);
1.15      mycroft  1962:                FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
                   1963:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1.1       cgd      1964:                vrele(fromnd.ni_dvp);
                   1965:                vrele(fvp);
                   1966:        }
                   1967:        return (error);
                   1968: }
                   1969:
                   1970: /*
                   1971:  * nfs link service
                   1972:  */
1.22      christos 1973: int
1.23      fvdl     1974: nfsrv_link(nfsd, slp, procp, mrq)
                   1975:        struct nfsrv_descript *nfsd;
                   1976:        struct nfssvc_sock *slp;
                   1977:        struct proc *procp;
                   1978:        struct mbuf **mrq;
1.1       cgd      1979: {
1.23      fvdl     1980:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1981:        struct mbuf *nam = nfsd->nd_nam;
                   1982:        caddr_t dpos = nfsd->nd_dpos;
                   1983:        struct ucred *cred = &nfsd->nd_cr;
1.1       cgd      1984:        struct nameidata nd;
1.54      augustss 1985:        u_int32_t *tl;
                   1986:        int32_t t1;
1.1       cgd      1987:        caddr_t bpos;
1.23      fvdl     1988:        int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   1989:        int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      1990:        char *cp2;
                   1991:        struct mbuf *mb, *mreq;
1.23      fvdl     1992:        struct vnode *vp, *xp, *dirp = (struct vnode *)0;
                   1993:        struct vattr dirfor, diraft, at;
                   1994:        nfsfh_t nfh, dnfh;
1.1       cgd      1995:        fhandle_t *fhp, *dfhp;
1.15      mycroft  1996:        u_quad_t frev;
1.1       cgd      1997:
                   1998:        fhp = &nfh.fh_generic;
                   1999:        dfhp = &dnfh.fh_generic;
                   2000:        nfsm_srvmtofh(fhp);
                   2001:        nfsm_srvmtofh(dfhp);
1.23      fvdl     2002:        nfsm_srvnamesiz(len);
                   2003:        error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
1.35      fvdl     2004:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2005:        if (error) {
                   2006:                nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2007:                nfsm_srvpostop_attr(getret, &at);
                   2008:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2009:                return (0);
                   2010:        }
                   2011:        if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)) != 0)
                   2012:                goto out1;
1.15      mycroft  2013:        nd.ni_cnd.cn_cred = cred;
                   2014:        nd.ni_cnd.cn_nameiop = CREATE;
                   2015:        nd.ni_cnd.cn_flags = LOCKPARENT;
1.23      fvdl     2016:        error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
1.35      fvdl     2017:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2018:        if (dirp) {
                   2019:                if (v3)
                   2020:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2021:                                procp);
                   2022:                else {
                   2023:                        vrele(dirp);
                   2024:                        dirp = (struct vnode *)0;
                   2025:                }
                   2026:        }
1.22      christos 2027:        if (error)
1.23      fvdl     2028:                goto out1;
                   2029:        xp = nd.ni_vp;
                   2030:        if (xp != NULL) {
                   2031:                error = EEXIST;
1.1       cgd      2032:                goto out;
1.23      fvdl     2033:        }
                   2034:        xp = nd.ni_dvp;
                   2035:        if (vp->v_mount != xp->v_mount)
                   2036:                error = EXDEV;
                   2037: out:
                   2038:        if (!error) {
                   2039:                nqsrv_getl(vp, ND_WRITE);
                   2040:                nqsrv_getl(xp, ND_WRITE);
                   2041:                error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
                   2042:        } else {
1.15      mycroft  2043:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2044:                if (nd.ni_dvp == nd.ni_vp)
                   2045:                        vrele(nd.ni_dvp);
                   2046:                else
                   2047:                        vput(nd.ni_dvp);
1.23      fvdl     2048:                if (nd.ni_vp)
                   2049:                        vrele(nd.ni_vp);
                   2050:        }
                   2051: out1:
                   2052:        if (v3)
                   2053:                getret = VOP_GETATTR(vp, &at, cred, procp);
                   2054:        if (dirp) {
                   2055:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
                   2056:                vrele(dirp);
1.1       cgd      2057:        }
                   2058:        vrele(vp);
1.23      fvdl     2059:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2060:        if (v3) {
                   2061:                nfsm_srvpostop_attr(getret, &at);
                   2062:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2063:                return (0);
                   2064:        }
1.1       cgd      2065:        nfsm_srvdone;
                   2066: }
                   2067:
                   2068: /*
                   2069:  * nfs symbolic link service
                   2070:  */
1.22      christos 2071: int
1.23      fvdl     2072: nfsrv_symlink(nfsd, slp, procp, mrq)
                   2073:        struct nfsrv_descript *nfsd;
                   2074:        struct nfssvc_sock *slp;
                   2075:        struct proc *procp;
                   2076:        struct mbuf **mrq;
1.1       cgd      2077: {
1.23      fvdl     2078:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2079:        struct mbuf *nam = nfsd->nd_nam;
                   2080:        caddr_t dpos = nfsd->nd_dpos;
                   2081:        struct ucred *cred = &nfsd->nd_cr;
                   2082:        struct vattr va, dirfor, diraft;
1.1       cgd      2083:        struct nameidata nd;
1.54      augustss 2084:        u_int32_t *tl;
                   2085:        int32_t t1;
1.1       cgd      2086:        struct nfsv2_sattr *sp;
1.23      fvdl     2087:        char *bpos, *pathcp = NULL, *cp2;
1.1       cgd      2088:        struct uio io;
                   2089:        struct iovec iv;
1.23      fvdl     2090:        int error = 0, cache, len, len2, dirfor_ret = 1, diraft_ret = 1;
                   2091:        int v3 = (nfsd->nd_flag & ND_NFSV3);
                   2092:        struct mbuf *mb, *mreq, *mb2;
                   2093:        struct vnode *dirp = (struct vnode *)0;
                   2094:        nfsfh_t nfh;
1.1       cgd      2095:        fhandle_t *fhp;
1.15      mycroft  2096:        u_quad_t frev;
1.1       cgd      2097:
1.23      fvdl     2098:        nd.ni_cnd.cn_nameiop = 0;
1.1       cgd      2099:        fhp = &nfh.fh_generic;
                   2100:        nfsm_srvmtofh(fhp);
1.23      fvdl     2101:        nfsm_srvnamesiz(len);
1.15      mycroft  2102:        nd.ni_cnd.cn_cred = cred;
                   2103:        nd.ni_cnd.cn_nameiop = CREATE;
1.23      fvdl     2104:        nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
                   2105:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.35      fvdl     2106:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2107:        if (dirp) {
                   2108:                if (v3)
                   2109:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2110:                                procp);
                   2111:                else {
                   2112:                        vrele(dirp);
                   2113:                        dirp = (struct vnode *)0;
                   2114:                }
                   2115:        }
1.22      christos 2116:        if (error)
1.1       cgd      2117:                goto out;
1.23      fvdl     2118:        VATTR_NULL(&va);
                   2119:        if (v3)
                   2120:                nfsm_srvsattr(&va);
1.1       cgd      2121:        nfsm_strsiz(len2, NFS_MAXPATHLEN);
                   2122:        MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
                   2123:        iv.iov_base = pathcp;
                   2124:        iv.iov_len = len2;
                   2125:        io.uio_resid = len2;
                   2126:        io.uio_offset = 0;
                   2127:        io.uio_iov = &iv;
                   2128:        io.uio_iovcnt = 1;
                   2129:        io.uio_segflg = UIO_SYSSPACE;
                   2130:        io.uio_rw = UIO_READ;
                   2131:        io.uio_procp = (struct proc *)0;
                   2132:        nfsm_mtouio(&io, len2);
1.23      fvdl     2133:        if (!v3) {
                   2134:                nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
                   2135:                va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
                   2136:        }
1.1       cgd      2137:        *(pathcp + len2) = '\0';
                   2138:        if (nd.ni_vp) {
1.23      fvdl     2139:                vrele(nd.ni_startdir);
                   2140:                free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
1.15      mycroft  2141:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2142:                if (nd.ni_dvp == nd.ni_vp)
                   2143:                        vrele(nd.ni_dvp);
                   2144:                else
                   2145:                        vput(nd.ni_dvp);
                   2146:                vrele(nd.ni_vp);
                   2147:                error = EEXIST;
                   2148:                goto out;
                   2149:        }
1.23      fvdl     2150:        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   2151:        error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp);
                   2152:        if (error)
                   2153:                vrele(nd.ni_startdir);
                   2154:        else {
                   2155:            if (v3) {
                   2156:                nd.ni_cnd.cn_nameiop = LOOKUP;
                   2157:                nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART | FOLLOW);
                   2158:                nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
                   2159:                nd.ni_cnd.cn_proc = procp;
                   2160:                nd.ni_cnd.cn_cred = cred;
                   2161:                error = lookup(&nd);
                   2162:                if (!error) {
1.44      perry    2163:                        memset((caddr_t)fhp, 0, sizeof(nfh));
1.23      fvdl     2164:                        fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
                   2165:                        error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
                   2166:                        if (!error)
                   2167:                                error = VOP_GETATTR(nd.ni_vp, &va, cred,
                   2168:                                        procp);
                   2169:                        vput(nd.ni_vp);
                   2170:                }
                   2171:            } else
                   2172:                vrele(nd.ni_startdir);
                   2173:            FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   2174:        }
1.1       cgd      2175: out:
                   2176:        if (pathcp)
                   2177:                FREE(pathcp, M_TEMP);
1.23      fvdl     2178:        if (dirp) {
                   2179:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
                   2180:                vrele(dirp);
                   2181:        }
                   2182:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2183:        if (v3) {
                   2184:                if (!error) {
                   2185:                        nfsm_srvpostop_fh(fhp);
                   2186:                        nfsm_srvpostop_attr(0, &va);
                   2187:                }
                   2188:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2189:        }
                   2190:        return (0);
1.1       cgd      2191: nfsmout:
1.23      fvdl     2192:        if (nd.ni_cnd.cn_nameiop) {
                   2193:                vrele(nd.ni_startdir);
                   2194:                free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
                   2195:        }
                   2196:        if (dirp)
                   2197:                vrele(dirp);
1.15      mycroft  2198:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2199:        if (nd.ni_dvp == nd.ni_vp)
                   2200:                vrele(nd.ni_dvp);
                   2201:        else
                   2202:                vput(nd.ni_dvp);
                   2203:        if (nd.ni_vp)
                   2204:                vrele(nd.ni_vp);
                   2205:        if (pathcp)
                   2206:                FREE(pathcp, M_TEMP);
                   2207:        return (error);
                   2208: }
                   2209:
                   2210: /*
                   2211:  * nfs mkdir service
                   2212:  */
1.22      christos 2213: int
1.23      fvdl     2214: nfsrv_mkdir(nfsd, slp, procp, mrq)
                   2215:        struct nfsrv_descript *nfsd;
                   2216:        struct nfssvc_sock *slp;
                   2217:        struct proc *procp;
                   2218:        struct mbuf **mrq;
1.1       cgd      2219: {
1.23      fvdl     2220:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2221:        struct mbuf *nam = nfsd->nd_nam;
                   2222:        caddr_t dpos = nfsd->nd_dpos;
                   2223:        struct ucred *cred = &nfsd->nd_cr;
                   2224:        struct vattr va, dirfor, diraft;
1.54      augustss 2225:        struct nfs_fattr *fp;
1.1       cgd      2226:        struct nameidata nd;
1.54      augustss 2227:        caddr_t cp;
                   2228:        u_int32_t *tl;
                   2229:        int32_t t1;
1.1       cgd      2230:        caddr_t bpos;
1.23      fvdl     2231:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   2232:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      2233:        char *cp2;
                   2234:        struct mbuf *mb, *mb2, *mreq;
1.23      fvdl     2235:        struct vnode *vp, *dirp = (struct vnode *)0;
                   2236:        nfsfh_t nfh;
1.1       cgd      2237:        fhandle_t *fhp;
1.15      mycroft  2238:        u_quad_t frev;
1.1       cgd      2239:
                   2240:        fhp = &nfh.fh_generic;
                   2241:        nfsm_srvmtofh(fhp);
1.23      fvdl     2242:        nfsm_srvnamesiz(len);
1.15      mycroft  2243:        nd.ni_cnd.cn_cred = cred;
                   2244:        nd.ni_cnd.cn_nameiop = CREATE;
                   2245:        nd.ni_cnd.cn_flags = LOCKPARENT;
1.23      fvdl     2246:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.35      fvdl     2247:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2248:        if (dirp) {
                   2249:                if (v3)
                   2250:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2251:                                procp);
                   2252:                else {
                   2253:                        vrele(dirp);
                   2254:                        dirp = (struct vnode *)0;
                   2255:                }
                   2256:        }
                   2257:        if (error) {
                   2258:                nfsm_reply(NFSX_WCCDATA(v3));
                   2259:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2260:                if (dirp)
                   2261:                        vrele(dirp);
                   2262:                return (0);
                   2263:        }
1.18      mycroft  2264:        VATTR_NULL(&va);
1.23      fvdl     2265:        if (v3) {
                   2266:                nfsm_srvsattr(&va);
                   2267:        } else {
                   2268:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                   2269:                va.va_mode = nfstov_mode(*tl++);
                   2270:        }
1.18      mycroft  2271:        va.va_type = VDIR;
1.1       cgd      2272:        vp = nd.ni_vp;
                   2273:        if (vp != NULL) {
1.15      mycroft  2274:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2275:                if (nd.ni_dvp == vp)
                   2276:                        vrele(nd.ni_dvp);
                   2277:                else
                   2278:                        vput(nd.ni_dvp);
                   2279:                vrele(vp);
                   2280:                error = EEXIST;
1.23      fvdl     2281:                goto out;
1.1       cgd      2282:        }
1.23      fvdl     2283:        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   2284:        error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   2285:        if (!error) {
                   2286:                vp = nd.ni_vp;
1.44      perry    2287:                memset((caddr_t)fhp, 0, sizeof(nfh));
1.23      fvdl     2288:                fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
                   2289:                error = VFS_VPTOFH(vp, &fhp->fh_fid);
                   2290:                if (!error)
                   2291:                        error = VOP_GETATTR(vp, &va, cred, procp);
1.1       cgd      2292:                vput(vp);
                   2293:        }
1.23      fvdl     2294: out:
                   2295:        if (dirp) {
                   2296:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
                   2297:                vrele(dirp);
                   2298:        }
                   2299:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2300:        if (v3) {
                   2301:                if (!error) {
                   2302:                        nfsm_srvpostop_fh(fhp);
                   2303:                        nfsm_srvpostop_attr(0, &va);
                   2304:                }
                   2305:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2306:        } else {
                   2307:                nfsm_srvfhtom(fhp, v3);
                   2308:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                   2309:                nfsm_srvfillattr(&va, fp);
                   2310:        }
                   2311:        return (0);
1.1       cgd      2312: nfsmout:
1.23      fvdl     2313:        if (dirp)
                   2314:                vrele(dirp);
1.15      mycroft  2315:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2316:        if (nd.ni_dvp == nd.ni_vp)
                   2317:                vrele(nd.ni_dvp);
                   2318:        else
                   2319:                vput(nd.ni_dvp);
                   2320:        if (nd.ni_vp)
                   2321:                vrele(nd.ni_vp);
                   2322:        return (error);
                   2323: }
                   2324:
                   2325: /*
                   2326:  * nfs rmdir service
                   2327:  */
1.22      christos 2328: int
1.23      fvdl     2329: nfsrv_rmdir(nfsd, slp, procp, mrq)
                   2330:        struct nfsrv_descript *nfsd;
                   2331:        struct nfssvc_sock *slp;
                   2332:        struct proc *procp;
                   2333:        struct mbuf **mrq;
1.1       cgd      2334: {
1.23      fvdl     2335:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2336:        struct mbuf *nam = nfsd->nd_nam;
                   2337:        caddr_t dpos = nfsd->nd_dpos;
                   2338:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 2339:        u_int32_t *tl;
                   2340:        int32_t t1;
1.1       cgd      2341:        caddr_t bpos;
1.23      fvdl     2342:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   2343:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      2344:        char *cp2;
                   2345:        struct mbuf *mb, *mreq;
1.23      fvdl     2346:        struct vnode *vp, *dirp = (struct vnode *)0;
                   2347:        struct vattr dirfor, diraft;
                   2348:        nfsfh_t nfh;
1.1       cgd      2349:        fhandle_t *fhp;
                   2350:        struct nameidata nd;
1.15      mycroft  2351:        u_quad_t frev;
1.1       cgd      2352:
                   2353:        fhp = &nfh.fh_generic;
                   2354:        nfsm_srvmtofh(fhp);
1.23      fvdl     2355:        nfsm_srvnamesiz(len);
1.15      mycroft  2356:        nd.ni_cnd.cn_cred = cred;
                   2357:        nd.ni_cnd.cn_nameiop = DELETE;
                   2358:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1.23      fvdl     2359:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.35      fvdl     2360:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2361:        if (dirp) {
                   2362:                if (v3)
                   2363:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2364:                                procp);
                   2365:                else {
                   2366:                        vrele(dirp);
                   2367:                        dirp = (struct vnode *)0;
                   2368:                }
                   2369:        }
                   2370:        if (error) {
                   2371:                nfsm_reply(NFSX_WCCDATA(v3));
                   2372:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2373:                if (dirp)
                   2374:                        vrele(dirp);
                   2375:                return (0);
                   2376:        }
1.1       cgd      2377:        vp = nd.ni_vp;
                   2378:        if (vp->v_type != VDIR) {
                   2379:                error = ENOTDIR;
                   2380:                goto out;
                   2381:        }
                   2382:        /*
                   2383:         * No rmdir "." please.
                   2384:         */
                   2385:        if (nd.ni_dvp == vp) {
                   2386:                error = EINVAL;
                   2387:                goto out;
                   2388:        }
                   2389:        /*
                   2390:         * The root of a mounted filesystem cannot be deleted.
                   2391:         */
                   2392:        if (vp->v_flag & VROOT)
                   2393:                error = EBUSY;
                   2394: out:
                   2395:        if (!error) {
1.23      fvdl     2396:                nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   2397:                nqsrv_getl(vp, ND_WRITE);
1.15      mycroft  2398:                error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1.1       cgd      2399:        } else {
1.15      mycroft  2400:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2401:                if (nd.ni_dvp == nd.ni_vp)
                   2402:                        vrele(nd.ni_dvp);
                   2403:                else
                   2404:                        vput(nd.ni_dvp);
                   2405:                vput(vp);
                   2406:        }
1.23      fvdl     2407:        if (dirp) {
                   2408:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
                   2409:                vrele(dirp);
                   2410:        }
                   2411:        nfsm_reply(NFSX_WCCDATA(v3));
                   2412:        if (v3) {
                   2413:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2414:                return (0);
                   2415:        }
1.1       cgd      2416:        nfsm_srvdone;
                   2417: }
                   2418:
                   2419: /*
                   2420:  * nfs readdir service
                   2421:  * - mallocs what it thinks is enough to read
                   2422:  *     count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
                   2423:  * - calls VOP_READDIR()
                   2424:  * - loops around building the reply
                   2425:  *     if the output generated exceeds count break out of loop
                   2426:  *     The nfsm_clget macro is used here so that the reply will be packed
                   2427:  *     tightly in mbuf clusters.
                   2428:  * - it only knows that it has encountered eof when the VOP_READDIR()
                   2429:  *     reads nothing
                   2430:  * - as such one readdir rpc will return eof false although you are there
                   2431:  *     and then the next will return eof
1.11      ws       2432:  * - it trims out records with d_fileno == 0
1.1       cgd      2433:  *     this doesn't matter for Unix clients, but they might confuse clients
                   2434:  *     for other os'.
1.25      jtk      2435:  * - it trims out records with d_type == DT_WHT
                   2436:  *     these cannot be seen through NFS (unless we extend the protocol)
1.1       cgd      2437:  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
                   2438:  *     than requested, but this may not apply to all filesystems. For
                   2439:  *     example, client NFS does not { although it is never remote mounted
                   2440:  *     anyhow }
1.23      fvdl     2441:  *     The alternate call nfsrv_readdirplus() does lookups as well.
1.1       cgd      2442:  * PS: The NFS protocol spec. does not clarify what the "count" byte
                   2443:  *     argument is a count of.. just name strings and file id's or the
                   2444:  *     entire reply rpc or ...
                   2445:  *     I tried just file name and id sizes and it confused the Sun client,
                   2446:  *     so I am using the full rpc size now. The "paranoia.." comment refers
                   2447:  *     to including the status longwords that are not a part of the dir.
                   2448:  *     "entry" structures, but are in the rpc.
                   2449:  */
1.15      mycroft  2450: struct flrep {
1.23      fvdl     2451:        nfsuint64 fl_off;
                   2452:        u_int32_t fl_postopok;
                   2453:        u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
                   2454:        u_int32_t fl_fhok;
                   2455:        u_int32_t fl_fhsize;
                   2456:        u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
1.15      mycroft  2457: };
                   2458:
1.22      christos 2459: int
1.23      fvdl     2460: nfsrv_readdir(nfsd, slp, procp, mrq)
                   2461:        struct nfsrv_descript *nfsd;
                   2462:        struct nfssvc_sock *slp;
                   2463:        struct proc *procp;
                   2464:        struct mbuf **mrq;
1.1       cgd      2465: {
1.23      fvdl     2466:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2467:        struct mbuf *nam = nfsd->nd_nam;
                   2468:        caddr_t dpos = nfsd->nd_dpos;
                   2469:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 2470:        char *bp, *be;
                   2471:        struct mbuf *mp;
                   2472:        struct dirent *dp;
                   2473:        caddr_t cp;
                   2474:        u_int32_t *tl;
                   2475:        int32_t t1;
1.1       cgd      2476:        caddr_t bpos;
1.15      mycroft  2477:        struct mbuf *mb, *mb2, *mreq, *mp2;
                   2478:        char *cpos, *cend, *cp2, *rbuf;
1.1       cgd      2479:        struct vnode *vp;
1.23      fvdl     2480:        struct vattr at;
                   2481:        nfsfh_t nfh;
1.1       cgd      2482:        fhandle_t *fhp;
                   2483:        struct uio io;
                   2484:        struct iovec iv;
1.23      fvdl     2485:        int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
                   2486:        int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
                   2487:        int v3 = (nfsd->nd_flag & ND_NFSV3);
                   2488:        u_quad_t frev, off, toff, verf;
1.38      fvdl     2489:        off_t *cookies = NULL, *cookiep;
                   2490:        nfsuint64 jar;
1.15      mycroft  2491:
1.1       cgd      2492:        fhp = &nfh.fh_generic;
                   2493:        nfsm_srvmtofh(fhp);
1.23      fvdl     2494:        if (v3) {
                   2495:                nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1.48      fair     2496:                toff = fxdr_hyper(tl);
1.23      fvdl     2497:                tl += 2;
1.48      fair     2498:                verf = fxdr_hyper(tl);
1.23      fvdl     2499:                tl += 2;
                   2500:        } else {
                   2501:                nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
                   2502:                toff = fxdr_unsigned(u_quad_t, *tl++);
                   2503:        }
                   2504:        off = toff;
1.1       cgd      2505:        cnt = fxdr_unsigned(int, *tl);
1.23      fvdl     2506:        siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
                   2507:        xfer = NFS_SRVMAXDATA(nfsd);
                   2508:        if (siz > xfer)
                   2509:                siz = xfer;
1.1       cgd      2510:        fullsiz = siz;
1.23      fvdl     2511:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl     2512:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.39      fvdl     2513:        if (!error && vp->v_type != VDIR) {
                   2514:                error = ENOTDIR;
                   2515:                vput(vp);
                   2516:        }
1.23      fvdl     2517:        if (error) {
                   2518:                nfsm_reply(NFSX_UNSIGNED);
                   2519:                nfsm_srvpostop_attr(getret, &at);
                   2520:                return (0);
                   2521:        }
                   2522:        nqsrv_getl(vp, ND_READ);
                   2523:        if (v3) {
                   2524:                error = getret = VOP_GETATTR(vp, &at, cred, procp);
                   2525: #ifdef NFS3_STRICTVERF
                   2526:                /*
                   2527:                 * XXX This check is too strict for Solaris 2.5 clients.
                   2528:                 */
                   2529:                if (!error && toff && verf != at.va_filerev)
                   2530:                        error = NFSERR_BAD_COOKIE;
                   2531: #endif
                   2532:        }
                   2533:        if (!error)
1.33      mycroft  2534:                error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
1.22      christos 2535:        if (error) {
1.1       cgd      2536:                vput(vp);
1.23      fvdl     2537:                nfsm_reply(NFSX_POSTOPATTR(v3));
                   2538:                nfsm_srvpostop_attr(getret, &at);
                   2539:                return (0);
1.1       cgd      2540:        }
1.42      fvdl     2541:        VOP_UNLOCK(vp, 0);
1.1       cgd      2542:        MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
                   2543: again:
                   2544:        iv.iov_base = rbuf;
                   2545:        iv.iov_len = fullsiz;
                   2546:        io.uio_iov = &iv;
                   2547:        io.uio_iovcnt = 1;
1.15      mycroft  2548:        io.uio_offset = (off_t)off;
1.1       cgd      2549:        io.uio_resid = fullsiz;
                   2550:        io.uio_segflg = UIO_SYSSPACE;
                   2551:        io.uio_rw = UIO_READ;
                   2552:        io.uio_procp = (struct proc *)0;
1.23      fvdl     2553:        eofflag = 0;
1.42      fvdl     2554:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.23      fvdl     2555:
1.42      fvdl     2556:        error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
1.23      fvdl     2557:
1.15      mycroft  2558:        off = (off_t)io.uio_offset;
1.23      fvdl     2559:        if (!cookies && !error)
                   2560:                error = NFSERR_PERM;
                   2561:        if (v3) {
                   2562:                getret = VOP_GETATTR(vp, &at, cred, procp);
                   2563:                if (!error)
                   2564:                        error = getret;
                   2565:        }
                   2566:
1.42      fvdl     2567:        VOP_UNLOCK(vp, 0);
1.1       cgd      2568:        if (error) {
                   2569:                vrele(vp);
1.42      fvdl     2570:                FREE((caddr_t)rbuf, M_TEMP);
1.23      fvdl     2571:                if (cookies)
                   2572:                        free((caddr_t)cookies, M_TEMP);
                   2573:                nfsm_reply(NFSX_POSTOPATTR(v3));
                   2574:                nfsm_srvpostop_attr(getret, &at);
                   2575:                return (0);
1.1       cgd      2576:        }
                   2577:        if (io.uio_resid) {
                   2578:                siz -= io.uio_resid;
                   2579:
                   2580:                /*
                   2581:                 * If nothing read, return eof
                   2582:                 * rpc reply
                   2583:                 */
                   2584:                if (siz == 0) {
                   2585:                        vrele(vp);
1.23      fvdl     2586:                        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
                   2587:                                2 * NFSX_UNSIGNED);
                   2588:                        if (v3) {
                   2589:                                nfsm_srvpostop_attr(getret, &at);
                   2590:                                nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1.48      fair     2591:                                txdr_hyper(at.va_filerev, tl);
1.23      fvdl     2592:                                tl += 2;
                   2593:                        } else
                   2594:                                nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.1       cgd      2595:                        *tl++ = nfs_false;
                   2596:                        *tl = nfs_true;
                   2597:                        FREE((caddr_t)rbuf, M_TEMP);
1.23      fvdl     2598:                        FREE((caddr_t)cookies, M_TEMP);
1.1       cgd      2599:                        return (0);
                   2600:                }
                   2601:        }
                   2602:
                   2603:        /*
                   2604:         * Check for degenerate cases of nothing useful read.
                   2605:         * If so go try again
                   2606:         */
1.8       ws       2607:        cpos = rbuf;
1.1       cgd      2608:        cend = rbuf + siz;
1.23      fvdl     2609:        dp = (struct dirent *)cpos;
                   2610:        cookiep = cookies;
                   2611:
1.28      fvdl     2612:        while (cpos < cend && ncookies > 0 &&
                   2613:                (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
1.23      fvdl     2614:                cpos += dp->d_reclen;
1.11      ws       2615:                dp = (struct dirent *)cpos;
1.23      fvdl     2616:                cookiep++;
                   2617:                ncookies--;
1.1       cgd      2618:        }
1.23      fvdl     2619:        if (cpos >= cend || ncookies == 0) {
                   2620:                toff = off;
1.1       cgd      2621:                siz = fullsiz;
                   2622:                goto again;
                   2623:        }
                   2624:
1.23      fvdl     2625:        len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
                   2626:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
                   2627:        if (v3) {
                   2628:                nfsm_srvpostop_attr(getret, &at);
                   2629:                nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.48      fair     2630:                txdr_hyper(at.va_filerev, tl);
1.23      fvdl     2631:        }
1.15      mycroft  2632:        mp = mp2 = mb;
                   2633:        bp = bpos;
                   2634:        be = bp + M_TRAILINGSPACE(mp);
                   2635:
                   2636:        /* Loop through the records and build reply */
1.23      fvdl     2637:        while (cpos < cend && ncookies > 0) {
1.25      jtk      2638:                if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
1.15      mycroft  2639:                        nlen = dp->d_namlen;
                   2640:                        rem = nfsm_rndup(nlen)-nlen;
1.23      fvdl     2641:                        len += (4 * NFSX_UNSIGNED + nlen + rem);
                   2642:                        if (v3)
                   2643:                                len += 2 * NFSX_UNSIGNED;
1.15      mycroft  2644:                        if (len > cnt) {
                   2645:                                eofflag = 0;
                   2646:                                break;
                   2647:                        }
                   2648:                        /*
                   2649:                         * Build the directory record xdr from
                   2650:                         * the dirent entry.
                   2651:                         */
                   2652:                        nfsm_clget;
                   2653:                        *tl = nfs_true;
                   2654:                        bp += NFSX_UNSIGNED;
1.23      fvdl     2655:                        if (v3) {
                   2656:                                nfsm_clget;
                   2657:                                *tl = 0;
                   2658:                                bp += NFSX_UNSIGNED;
                   2659:                        }
1.15      mycroft  2660:                        nfsm_clget;
                   2661:                        *tl = txdr_unsigned(dp->d_fileno);
                   2662:                        bp += NFSX_UNSIGNED;
                   2663:                        nfsm_clget;
                   2664:                        *tl = txdr_unsigned(nlen);
                   2665:                        bp += NFSX_UNSIGNED;
                   2666:
                   2667:                        /* And loop around copying the name */
                   2668:                        xfer = nlen;
                   2669:                        cp = dp->d_name;
                   2670:                        while (xfer > 0) {
                   2671:                                nfsm_clget;
                   2672:                                if ((bp+xfer) > be)
                   2673:                                        tsiz = be-bp;
                   2674:                                else
                   2675:                                        tsiz = xfer;
1.44      perry    2676:                                memcpy(bp, cp, tsiz);
1.15      mycroft  2677:                                bp += tsiz;
                   2678:                                xfer -= tsiz;
                   2679:                                if (xfer > 0)
                   2680:                                        cp += tsiz;
                   2681:                        }
1.23      fvdl     2682:                        /* And null pad to an int32_t boundary */
1.15      mycroft  2683:                        for (i = 0; i < rem; i++)
                   2684:                                *bp++ = '\0';
                   2685:                        nfsm_clget;
                   2686:
                   2687:                        /* Finish off the record */
1.48      fair     2688:                        txdr_hyper(*cookiep, &jar);
1.23      fvdl     2689:                        if (v3) {
1.38      fvdl     2690:                                *tl = jar.nfsuquad[0];
1.23      fvdl     2691:                                bp += NFSX_UNSIGNED;
                   2692:                                nfsm_clget;
                   2693:                        }
1.38      fvdl     2694:                        *tl = jar.nfsuquad[1];
1.15      mycroft  2695:                        bp += NFSX_UNSIGNED;
                   2696:                }
                   2697:                cpos += dp->d_reclen;
                   2698:                dp = (struct dirent *)cpos;
1.23      fvdl     2699:                cookiep++;
                   2700:                ncookies--;
1.15      mycroft  2701:        }
1.1       cgd      2702:        vrele(vp);
1.15      mycroft  2703:        nfsm_clget;
                   2704:        *tl = nfs_false;
                   2705:        bp += NFSX_UNSIGNED;
                   2706:        nfsm_clget;
                   2707:        if (eofflag)
                   2708:                *tl = nfs_true;
                   2709:        else
                   2710:                *tl = nfs_false;
                   2711:        bp += NFSX_UNSIGNED;
                   2712:        if (mp != mb) {
                   2713:                if (bp < be)
                   2714:                        mp->m_len = bp - mtod(mp, caddr_t);
                   2715:        } else
                   2716:                mp->m_len += bp - bpos;
1.23      fvdl     2717:        FREE((caddr_t)rbuf, M_TEMP);
                   2718:        FREE((caddr_t)cookies, M_TEMP);
1.15      mycroft  2719:        nfsm_srvdone;
                   2720: }
                   2721:
1.22      christos 2722: int
1.23      fvdl     2723: nfsrv_readdirplus(nfsd, slp, procp, mrq)
                   2724:        struct nfsrv_descript *nfsd;
                   2725:        struct nfssvc_sock *slp;
                   2726:        struct proc *procp;
                   2727:        struct mbuf **mrq;
1.15      mycroft  2728: {
1.23      fvdl     2729:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2730:        struct mbuf *nam = nfsd->nd_nam;
                   2731:        caddr_t dpos = nfsd->nd_dpos;
                   2732:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 2733:        char *bp, *be;
                   2734:        struct mbuf *mp;
                   2735:        struct dirent *dp;
                   2736:        caddr_t cp;
                   2737:        u_int32_t *tl;
                   2738:        int32_t t1;
1.15      mycroft  2739:        caddr_t bpos;
                   2740:        struct mbuf *mb, *mb2, *mreq, *mp2;
                   2741:        char *cpos, *cend, *cp2, *rbuf;
                   2742:        struct vnode *vp, *nvp;
                   2743:        struct flrep fl;
1.23      fvdl     2744:        nfsfh_t nfh;
                   2745:        fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
1.15      mycroft  2746:        struct uio io;
                   2747:        struct iovec iv;
1.23      fvdl     2748:        struct vattr va, at, *vap = &va;
                   2749:        struct nfs_fattr *fp;
                   2750:        int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
                   2751:        int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
                   2752:        u_quad_t frev, off, toff, verf;
1.38      fvdl     2753:        off_t *cookies = NULL, *cookiep;
1.15      mycroft  2754:
                   2755:        fhp = &nfh.fh_generic;
                   2756:        nfsm_srvmtofh(fhp);
1.23      fvdl     2757:        nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
1.48      fair     2758:        toff = fxdr_hyper(tl);
1.23      fvdl     2759:        tl += 2;
1.48      fair     2760:        verf = fxdr_hyper(tl);
1.23      fvdl     2761:        tl += 2;
                   2762:        siz = fxdr_unsigned(int, *tl++);
                   2763:        cnt = fxdr_unsigned(int, *tl);
                   2764:        off = toff;
                   2765:        siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
                   2766:        xfer = NFS_SRVMAXDATA(nfsd);
                   2767:        if (siz > xfer)
                   2768:                siz = xfer;
1.15      mycroft  2769:        fullsiz = siz;
1.23      fvdl     2770:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl     2771:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.39      fvdl     2772:        if (!error && vp->v_type != VDIR) {
                   2773:                error = ENOTDIR;
                   2774:                vput(vp);
                   2775:        }
1.23      fvdl     2776:        if (error) {
                   2777:                nfsm_reply(NFSX_UNSIGNED);
                   2778:                nfsm_srvpostop_attr(getret, &at);
                   2779:                return (0);
                   2780:        }
                   2781:        error = getret = VOP_GETATTR(vp, &at, cred, procp);
                   2782: #ifdef NFS3_STRICTVERF
                   2783:        /*
                   2784:         * XXX This check is too strict for Solaris 2.5 clients.
                   2785:         */
                   2786:        if (!error && toff && verf != at.va_filerev)
                   2787:                error = NFSERR_BAD_COOKIE;
                   2788: #endif
                   2789:        if (!error) {
                   2790:                nqsrv_getl(vp, ND_READ);
1.33      mycroft  2791:                error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
1.23      fvdl     2792:        }
1.22      christos 2793:        if (error) {
1.15      mycroft  2794:                vput(vp);
1.23      fvdl     2795:                nfsm_reply(NFSX_V3POSTOPATTR);
                   2796:                nfsm_srvpostop_attr(getret, &at);
                   2797:                return (0);
1.15      mycroft  2798:        }
1.42      fvdl     2799:        VOP_UNLOCK(vp, 0);
1.23      fvdl     2800:
1.15      mycroft  2801:        MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
                   2802: again:
                   2803:        iv.iov_base = rbuf;
                   2804:        iv.iov_len = fullsiz;
                   2805:        io.uio_iov = &iv;
                   2806:        io.uio_iovcnt = 1;
                   2807:        io.uio_offset = (off_t)off;
                   2808:        io.uio_resid = fullsiz;
                   2809:        io.uio_segflg = UIO_SYSSPACE;
                   2810:        io.uio_rw = UIO_READ;
                   2811:        io.uio_procp = (struct proc *)0;
1.23      fvdl     2812:        eofflag = 0;
                   2813:
1.42      fvdl     2814:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   2815:
                   2816:        error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
1.23      fvdl     2817:
                   2818:        off = (u_quad_t)io.uio_offset;
                   2819:        getret = VOP_GETATTR(vp, &at, cred, procp);
                   2820:
1.42      fvdl     2821:        VOP_UNLOCK(vp, 0);
1.36      fvdl     2822:
                   2823:        /*
                   2824:         * If the VGET operation doesn't work for this filesystem,
                   2825:         * we can't support readdirplus. Returning NOTSUPP should
                   2826:         * make clients fall back to plain readdir.
                   2827:         * There's no need to check for VPTOFH as well, we wouldn't
                   2828:         * even be here otherwise.
                   2829:         */
                   2830:        if (!getret) {
                   2831:                if ((getret = VFS_VGET(vp->v_mount, at.va_fileid, &nvp)))
                   2832:                        getret = (getret == EOPNOTSUPP) ?
                   2833:                                NFSERR_NOTSUPP : NFSERR_IO;
                   2834:                else
                   2835:                        vput(nvp);
                   2836:        }
                   2837:
1.23      fvdl     2838:        if (!cookies && !error)
                   2839:                error = NFSERR_PERM;
                   2840:        if (!error)
                   2841:                error = getret;
1.15      mycroft  2842:        if (error) {
                   2843:                vrele(vp);
1.23      fvdl     2844:                if (cookies)
1.42      fvdl     2845:                        FREE((caddr_t)cookies, M_TEMP);
                   2846:                FREE((caddr_t)rbuf, M_TEMP);
1.23      fvdl     2847:                nfsm_reply(NFSX_V3POSTOPATTR);
                   2848:                nfsm_srvpostop_attr(getret, &at);
                   2849:                return (0);
1.15      mycroft  2850:        }
                   2851:        if (io.uio_resid) {
                   2852:                siz -= io.uio_resid;
                   2853:
                   2854:                /*
                   2855:                 * If nothing read, return eof
                   2856:                 * rpc reply
                   2857:                 */
                   2858:                if (siz == 0) {
                   2859:                        vrele(vp);
1.23      fvdl     2860:                        nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
                   2861:                                2 * NFSX_UNSIGNED);
                   2862:                        nfsm_srvpostop_attr(getret, &at);
                   2863:                        nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1.48      fair     2864:                        txdr_hyper(at.va_filerev, tl);
1.23      fvdl     2865:                        tl += 2;
1.15      mycroft  2866:                        *tl++ = nfs_false;
                   2867:                        *tl = nfs_true;
1.23      fvdl     2868:                        FREE((caddr_t)cookies, M_TEMP);
1.15      mycroft  2869:                        FREE((caddr_t)rbuf, M_TEMP);
                   2870:                        return (0);
                   2871:                }
                   2872:        }
                   2873:
                   2874:        /*
                   2875:         * Check for degenerate cases of nothing useful read.
                   2876:         * If so go try again
                   2877:         */
                   2878:        cpos = rbuf;
                   2879:        cend = rbuf + siz;
1.23      fvdl     2880:        dp = (struct dirent *)cpos;
                   2881:        cookiep = cookies;
                   2882:
1.29      fvdl     2883:        while (cpos < cend && ncookies > 0 &&
                   2884:                (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
1.23      fvdl     2885:                cpos += dp->d_reclen;
1.15      mycroft  2886:                dp = (struct dirent *)cpos;
1.23      fvdl     2887:                cookiep++;
                   2888:                ncookies--;
1.15      mycroft  2889:        }
1.23      fvdl     2890:        if (cpos >= cend || ncookies == 0) {
                   2891:                toff = off;
1.15      mycroft  2892:                siz = fullsiz;
                   2893:                goto again;
                   2894:        }
                   2895:
1.23      fvdl     2896:        dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
                   2897:        nfsm_reply(cnt);
                   2898:        nfsm_srvpostop_attr(getret, &at);
                   2899:        nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.48      fair     2900:        txdr_hyper(at.va_filerev, tl);
1.15      mycroft  2901:        mp = mp2 = mb;
                   2902:        bp = bpos;
                   2903:        be = bp + M_TRAILINGSPACE(mp);
1.1       cgd      2904:
                   2905:        /* Loop through the records and build reply */
1.23      fvdl     2906:        while (cpos < cend && ncookies > 0) {
1.25      jtk      2907:                if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
1.1       cgd      2908:                        nlen = dp->d_namlen;
                   2909:                        rem = nfsm_rndup(nlen)-nlen;
                   2910:
                   2911:                        /*
1.15      mycroft  2912:                         * For readdir_and_lookup get the vnode using
                   2913:                         * the file number.
1.1       cgd      2914:                         */
1.15      mycroft  2915:                        if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
                   2916:                                goto invalid;
1.44      perry    2917:                        memset((caddr_t)nfhp, 0, NFSX_V3FH);
1.23      fvdl     2918:                        nfhp->fh_fsid =
1.15      mycroft  2919:                                nvp->v_mount->mnt_stat.f_fsid;
1.23      fvdl     2920:                        if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
1.15      mycroft  2921:                                vput(nvp);
                   2922:                                goto invalid;
                   2923:                        }
1.23      fvdl     2924:                        if (VOP_GETATTR(nvp, vap, cred, procp)) {
1.15      mycroft  2925:                                vput(nvp);
                   2926:                                goto invalid;
                   2927:                        }
                   2928:                        vput(nvp);
1.23      fvdl     2929:
                   2930:                        /*
                   2931:                         * If either the dircount or maxcount will be
                   2932:                         * exceeded, get out now. Both of these lengths
                   2933:                         * are calculated conservatively, including all
                   2934:                         * XDR overheads.
                   2935:                         */
1.52      fvdl     2936:                        len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
1.23      fvdl     2937:                                NFSX_V3POSTOPATTR);
                   2938:                        dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
                   2939:                        if (len > cnt || dirlen > fullsiz) {
1.1       cgd      2940:                                eofflag = 0;
                   2941:                                break;
                   2942:                        }
1.23      fvdl     2943:
1.15      mycroft  2944:                        /*
                   2945:                         * Build the directory record xdr from
                   2946:                         * the dirent entry.
                   2947:                         */
1.23      fvdl     2948:                        fp = (struct nfs_fattr *)&fl.fl_fattr;
                   2949:                        nfsm_srvfillattr(vap, fp);
                   2950:                        fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
                   2951:                        fl.fl_fhok = nfs_true;
                   2952:                        fl.fl_postopok = nfs_true;
1.48      fair     2953:                        txdr_hyper(*cookiep, fl.fl_off.nfsuquad);
1.23      fvdl     2954:
1.1       cgd      2955:                        nfsm_clget;
                   2956:                        *tl = nfs_true;
                   2957:                        bp += NFSX_UNSIGNED;
1.23      fvdl     2958:                        nfsm_clget;
                   2959:                        *tl = 0;
                   2960:                        bp += NFSX_UNSIGNED;
1.1       cgd      2961:                        nfsm_clget;
1.11      ws       2962:                        *tl = txdr_unsigned(dp->d_fileno);
1.1       cgd      2963:                        bp += NFSX_UNSIGNED;
                   2964:                        nfsm_clget;
                   2965:                        *tl = txdr_unsigned(nlen);
                   2966:                        bp += NFSX_UNSIGNED;
                   2967:
1.15      mycroft  2968:                        /* And loop around copying the name */
1.1       cgd      2969:                        xfer = nlen;
                   2970:                        cp = dp->d_name;
                   2971:                        while (xfer > 0) {
                   2972:                                nfsm_clget;
1.23      fvdl     2973:                                if ((bp + xfer) > be)
                   2974:                                        tsiz = be - bp;
1.1       cgd      2975:                                else
                   2976:                                        tsiz = xfer;
1.44      perry    2977:                                memcpy(bp, cp, tsiz);
1.1       cgd      2978:                                bp += tsiz;
                   2979:                                xfer -= tsiz;
                   2980:                                if (xfer > 0)
                   2981:                                        cp += tsiz;
                   2982:                        }
1.23      fvdl     2983:                        /* And null pad to an int32_t boundary */
1.1       cgd      2984:                        for (i = 0; i < rem; i++)
                   2985:                                *bp++ = '\0';
                   2986:
1.23      fvdl     2987:                        /*
                   2988:                         * Now copy the flrep structure out.
                   2989:                         */
                   2990:                        xfer = sizeof (struct flrep);
                   2991:                        cp = (caddr_t)&fl;
                   2992:                        while (xfer > 0) {
                   2993:                                nfsm_clget;
                   2994:                                if ((bp + xfer) > be)
                   2995:                                        tsiz = be - bp;
                   2996:                                else
                   2997:                                        tsiz = xfer;
1.44      perry    2998:                                memcpy(bp, cp, tsiz);
1.23      fvdl     2999:                                bp += tsiz;
                   3000:                                xfer -= tsiz;
                   3001:                                if (xfer > 0)
                   3002:                                        cp += tsiz;
                   3003:                        }
1.8       ws       3004:                }
1.15      mycroft  3005: invalid:
1.1       cgd      3006:                cpos += dp->d_reclen;
1.11      ws       3007:                dp = (struct dirent *)cpos;
1.23      fvdl     3008:                cookiep++;
                   3009:                ncookies--;
1.1       cgd      3010:        }
1.15      mycroft  3011:        vrele(vp);
1.1       cgd      3012:        nfsm_clget;
                   3013:        *tl = nfs_false;
                   3014:        bp += NFSX_UNSIGNED;
                   3015:        nfsm_clget;
                   3016:        if (eofflag)
                   3017:                *tl = nfs_true;
                   3018:        else
                   3019:                *tl = nfs_false;
                   3020:        bp += NFSX_UNSIGNED;
1.15      mycroft  3021:        if (mp != mb) {
                   3022:                if (bp < be)
                   3023:                        mp->m_len = bp - mtod(mp, caddr_t);
                   3024:        } else
                   3025:                mp->m_len += bp - bpos;
1.23      fvdl     3026:        FREE((caddr_t)cookies, M_TEMP);
                   3027:        FREE((caddr_t)rbuf, M_TEMP);
                   3028:        nfsm_srvdone;
                   3029: }
                   3030:
                   3031: /*
                   3032:  * nfs commit service
                   3033:  */
                   3034: int
                   3035: nfsrv_commit(nfsd, slp, procp, mrq)
                   3036:        struct nfsrv_descript *nfsd;
                   3037:        struct nfssvc_sock *slp;
                   3038:        struct proc *procp;
                   3039:        struct mbuf **mrq;
                   3040: {
                   3041:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3042:        struct mbuf *nam = nfsd->nd_nam;
                   3043:        caddr_t dpos = nfsd->nd_dpos;
                   3044:        struct ucred *cred = &nfsd->nd_cr;
                   3045:        struct vattr bfor, aft;
                   3046:        struct vnode *vp;
                   3047:        nfsfh_t nfh;
                   3048:        fhandle_t *fhp;
1.54      augustss 3049:        u_int32_t *tl;
                   3050:        int32_t t1;
1.23      fvdl     3051:        caddr_t bpos;
                   3052:        int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
                   3053:        char *cp2;
                   3054:        struct mbuf *mb, *mb2, *mreq;
                   3055:        u_quad_t frev, off;
                   3056:
                   3057: #ifndef nolint
                   3058:        cache = 0;
                   3059: #endif
                   3060:        fhp = &nfh.fh_generic;
                   3061:        nfsm_srvmtofh(fhp);
                   3062:        nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
                   3063:
1.48      fair     3064:        off = fxdr_hyper(tl);
1.23      fvdl     3065:        tl += 2;
                   3066:        cnt = fxdr_unsigned(int, *tl);
                   3067:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl     3068:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3069:        if (error) {
                   3070:                nfsm_reply(2 * NFSX_UNSIGNED);
                   3071:                nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
                   3072:                return (0);
                   3073:        }
                   3074:        for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
1.54.4.1! he       3075:        error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, off + cnt, procp);
1.23      fvdl     3076:        aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
                   3077:        vput(vp);
                   3078:        nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
                   3079:        nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
                   3080:        if (!error) {
                   3081:                nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
                   3082:                *tl++ = txdr_unsigned(boottime.tv_sec);
                   3083:                *tl = txdr_unsigned(boottime.tv_usec);
                   3084:        } else
                   3085:                return (0);
1.1       cgd      3086:        nfsm_srvdone;
                   3087: }
                   3088:
                   3089: /*
                   3090:  * nfs statfs service
                   3091:  */
1.22      christos 3092: int
1.23      fvdl     3093: nfsrv_statfs(nfsd, slp, procp, mrq)
                   3094:        struct nfsrv_descript *nfsd;
                   3095:        struct nfssvc_sock *slp;
                   3096:        struct proc *procp;
                   3097:        struct mbuf **mrq;
1.1       cgd      3098: {
1.23      fvdl     3099:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3100:        struct mbuf *nam = nfsd->nd_nam;
                   3101:        caddr_t dpos = nfsd->nd_dpos;
                   3102:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 3103:        struct statfs *sf;
                   3104:        struct nfs_statfs *sfp;
                   3105:        u_int32_t *tl;
                   3106:        int32_t t1;
1.1       cgd      3107:        caddr_t bpos;
1.23      fvdl     3108:        int error = 0, rdonly, cache, getret = 1;
                   3109:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      3110:        char *cp2;
                   3111:        struct mbuf *mb, *mb2, *mreq;
                   3112:        struct vnode *vp;
1.23      fvdl     3113:        struct vattr at;
                   3114:        nfsfh_t nfh;
1.1       cgd      3115:        fhandle_t *fhp;
                   3116:        struct statfs statfs;
1.23      fvdl     3117:        u_quad_t frev, tval;
1.1       cgd      3118:
1.23      fvdl     3119: #ifndef nolint
                   3120:        cache = 0;
                   3121: #endif
1.1       cgd      3122:        fhp = &nfh.fh_generic;
                   3123:        nfsm_srvmtofh(fhp);
1.23      fvdl     3124:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl     3125:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3126:        if (error) {
                   3127:                nfsm_reply(NFSX_UNSIGNED);
                   3128:                nfsm_srvpostop_attr(getret, &at);
                   3129:                return (0);
                   3130:        }
1.1       cgd      3131:        sf = &statfs;
1.23      fvdl     3132:        error = VFS_STATFS(vp->v_mount, sf, procp);
                   3133:        getret = VOP_GETATTR(vp, &at, cred, procp);
1.1       cgd      3134:        vput(vp);
1.23      fvdl     3135:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
                   3136:        if (v3)
                   3137:                nfsm_srvpostop_attr(getret, &at);
                   3138:        if (error)
                   3139:                return (0);
                   3140:        nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
                   3141:        if (v3) {
1.47      mycroft  3142:                tval = (u_quad_t)((quad_t)sf->f_blocks * (quad_t)sf->f_bsize);
1.48      fair     3143:                txdr_hyper(tval, &sfp->sf_tbytes);
1.47      mycroft  3144:                tval = (u_quad_t)((quad_t)sf->f_bfree * (quad_t)sf->f_bsize);
1.48      fair     3145:                txdr_hyper(tval, &sfp->sf_fbytes);
1.47      mycroft  3146:                tval = (u_quad_t)((quad_t)sf->f_bavail * (quad_t)sf->f_bsize);
1.48      fair     3147:                txdr_hyper(tval, &sfp->sf_abytes);
1.47      mycroft  3148:                tval = (u_quad_t)sf->f_files;
1.48      fair     3149:                txdr_hyper(tval, &sfp->sf_tfiles);
1.47      mycroft  3150:                tval = (u_quad_t)sf->f_ffree;
1.48      fair     3151:                txdr_hyper(tval, &sfp->sf_ffiles);
                   3152:                txdr_hyper(tval, &sfp->sf_afiles);
1.23      fvdl     3153:                sfp->sf_invarsec = 0;
                   3154:        } else {
                   3155:                sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
                   3156:                sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
                   3157:                sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
                   3158:                sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
                   3159:                sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
                   3160:        }
                   3161:        nfsm_srvdone;
                   3162: }
                   3163:
                   3164: /*
                   3165:  * nfs fsinfo service
                   3166:  */
                   3167: int
                   3168: nfsrv_fsinfo(nfsd, slp, procp, mrq)
                   3169:        struct nfsrv_descript *nfsd;
                   3170:        struct nfssvc_sock *slp;
                   3171:        struct proc *procp;
                   3172:        struct mbuf **mrq;
                   3173: {
                   3174:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3175:        struct mbuf *nam = nfsd->nd_nam;
                   3176:        caddr_t dpos = nfsd->nd_dpos;
                   3177:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 3178:        u_int32_t *tl;
                   3179:        struct nfsv3_fsinfo *sip;
                   3180:        int32_t t1;
1.23      fvdl     3181:        caddr_t bpos;
                   3182:        int error = 0, rdonly, cache, getret = 1, pref;
                   3183:        char *cp2;
                   3184:        struct mbuf *mb, *mb2, *mreq;
                   3185:        struct vnode *vp;
                   3186:        struct vattr at;
                   3187:        nfsfh_t nfh;
                   3188:        fhandle_t *fhp;
1.37      fvdl     3189:        u_quad_t frev, maxfsize;
                   3190:        struct statfs sb;
1.23      fvdl     3191:
                   3192: #ifndef nolint
                   3193:        cache = 0;
                   3194: #endif
                   3195:        fhp = &nfh.fh_generic;
                   3196:        nfsm_srvmtofh(fhp);
                   3197:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl     3198:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3199:        if (error) {
                   3200:                nfsm_reply(NFSX_UNSIGNED);
                   3201:                nfsm_srvpostop_attr(getret, &at);
                   3202:                return (0);
1.15      mycroft  3203:        }
1.37      fvdl     3204:
                   3205:        /* XXX Try to make a guess on the max file size. */
                   3206:        VFS_STATFS(vp->v_mount, &sb, (struct proc *)0);
                   3207:        maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
                   3208:
1.23      fvdl     3209:        getret = VOP_GETATTR(vp, &at, cred, procp);
                   3210:        vput(vp);
                   3211:        nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
                   3212:        nfsm_srvpostop_attr(getret, &at);
                   3213:        nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
                   3214:
                   3215:        /*
                   3216:         * XXX
                   3217:         * There should be file system VFS OP(s) to get this information.
                   3218:         * For now, assume ufs.
                   3219:         */
                   3220:        if (slp->ns_so->so_type == SOCK_DGRAM)
                   3221:                pref = NFS_MAXDGRAMDATA;
                   3222:        else
                   3223:                pref = NFS_MAXDATA;
                   3224:        sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
                   3225:        sip->fs_rtpref = txdr_unsigned(pref);
                   3226:        sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
                   3227:        sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
                   3228:        sip->fs_wtpref = txdr_unsigned(pref);
                   3229:        sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
                   3230:        sip->fs_dtpref = txdr_unsigned(pref);
1.48      fair     3231:        txdr_hyper(maxfsize, &sip->fs_maxfilesize);
1.23      fvdl     3232:        sip->fs_timedelta.nfsv3_sec = 0;
                   3233:        sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
                   3234:        sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
                   3235:                NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
                   3236:                NFSV3FSINFO_CANSETTIME);
                   3237:        nfsm_srvdone;
                   3238: }
                   3239:
                   3240: /*
                   3241:  * nfs pathconf service
                   3242:  */
                   3243: int
                   3244: nfsrv_pathconf(nfsd, slp, procp, mrq)
                   3245:        struct nfsrv_descript *nfsd;
                   3246:        struct nfssvc_sock *slp;
                   3247:        struct proc *procp;
                   3248:        struct mbuf **mrq;
                   3249: {
                   3250:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3251:        struct mbuf *nam = nfsd->nd_nam;
                   3252:        caddr_t dpos = nfsd->nd_dpos;
                   3253:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 3254:        u_int32_t *tl;
                   3255:        struct nfsv3_pathconf *pc;
                   3256:        int32_t t1;
1.23      fvdl     3257:        caddr_t bpos;
1.24      cgd      3258:        int error = 0, rdonly, cache, getret = 1;
                   3259:        register_t linkmax, namemax, chownres, notrunc;
1.23      fvdl     3260:        char *cp2;
                   3261:        struct mbuf *mb, *mb2, *mreq;
                   3262:        struct vnode *vp;
                   3263:        struct vattr at;
                   3264:        nfsfh_t nfh;
                   3265:        fhandle_t *fhp;
                   3266:        u_quad_t frev;
                   3267:
                   3268: #ifndef nolint
                   3269:        cache = 0;
                   3270: #endif
                   3271:        fhp = &nfh.fh_generic;
                   3272:        nfsm_srvmtofh(fhp);
                   3273:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.35      fvdl     3274:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3275:        if (error) {
                   3276:                nfsm_reply(NFSX_UNSIGNED);
                   3277:                nfsm_srvpostop_attr(getret, &at);
                   3278:                return (0);
                   3279:        }
                   3280:        error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
                   3281:        if (!error)
                   3282:                error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
                   3283:        if (!error)
                   3284:                error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
                   3285:        if (!error)
                   3286:                error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
                   3287:        getret = VOP_GETATTR(vp, &at, cred, procp);
                   3288:        vput(vp);
                   3289:        nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
                   3290:        nfsm_srvpostop_attr(getret, &at);
                   3291:        if (error)
                   3292:                return (0);
                   3293:        nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
                   3294:
                   3295:        pc->pc_linkmax = txdr_unsigned(linkmax);
                   3296:        pc->pc_namemax = txdr_unsigned(namemax);
                   3297:        pc->pc_notrunc = txdr_unsigned(notrunc);
                   3298:        pc->pc_chownrestricted = txdr_unsigned(chownres);
                   3299:
                   3300:        /*
                   3301:         * These should probably be supported by VOP_PATHCONF(), but
                   3302:         * until msdosfs is exportable (why would you want to?), the
                   3303:         * Unix defaults should be ok.
                   3304:         */
                   3305:        pc->pc_caseinsensitive = nfs_false;
                   3306:        pc->pc_casepreserving = nfs_true;
1.1       cgd      3307:        nfsm_srvdone;
                   3308: }
                   3309:
                   3310: /*
                   3311:  * Null operation, used by clients to ping server
                   3312:  */
                   3313: /* ARGSUSED */
1.22      christos 3314: int
1.23      fvdl     3315: nfsrv_null(nfsd, slp, procp, mrq)
                   3316:        struct nfsrv_descript *nfsd;
                   3317:        struct nfssvc_sock *slp;
                   3318:        struct proc *procp;
                   3319:        struct mbuf **mrq;
1.1       cgd      3320: {
1.23      fvdl     3321:        struct mbuf *mrep = nfsd->nd_mrep;
1.1       cgd      3322:        caddr_t bpos;
1.23      fvdl     3323:        int error = NFSERR_RETVOID, cache = 0;
1.1       cgd      3324:        struct mbuf *mb, *mreq;
1.15      mycroft  3325:        u_quad_t frev;
1.1       cgd      3326:
                   3327:        nfsm_reply(0);
1.23      fvdl     3328:        return (0);
1.1       cgd      3329: }
                   3330:
                   3331: /*
                   3332:  * No operation, used for obsolete procedures
                   3333:  */
                   3334: /* ARGSUSED */
1.22      christos 3335: int
1.23      fvdl     3336: nfsrv_noop(nfsd, slp, procp, mrq)
                   3337:        struct nfsrv_descript *nfsd;
                   3338:        struct nfssvc_sock *slp;
                   3339:        struct proc *procp;
                   3340:        struct mbuf **mrq;
1.1       cgd      3341: {
1.23      fvdl     3342:        struct mbuf *mrep = nfsd->nd_mrep;
1.1       cgd      3343:        caddr_t bpos;
1.22      christos 3344:        int error, cache = 0;
1.1       cgd      3345:        struct mbuf *mb, *mreq;
1.15      mycroft  3346:        u_quad_t frev;
1.1       cgd      3347:
1.15      mycroft  3348:        if (nfsd->nd_repstat)
                   3349:                error = nfsd->nd_repstat;
1.2       cgd      3350:        else
                   3351:                error = EPROCUNAVAIL;
1.1       cgd      3352:        nfsm_reply(0);
1.23      fvdl     3353:        return (0);
1.1       cgd      3354: }
                   3355:
                   3356: /*
                   3357:  * Perform access checking for vnodes obtained from file handles that would
                   3358:  * refer to files already opened by a Unix client. You cannot just use
                   3359:  * vn_writechk() and VOP_ACCESS() for two reasons.
1.15      mycroft  3360:  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
1.27      fvdl     3361:  * 2 - The owner is to be given access irrespective of mode bits for some
                   3362:  *     operations, so that processes that chmod after opening a file don't
                   3363:  *     break. I don't like this because it opens a security hole, but since
                   3364:  *     the nfs server opens a security hole the size of a barn door anyhow,
                   3365:  *     what the heck.
1.31      fvdl     3366:  *
                   3367:  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
                   3368:  * will return EPERM instead of EACCESS. EPERM is always an error.
1.1       cgd      3369:  */
1.22      christos 3370: int
1.27      fvdl     3371: nfsrv_access(vp, flags, cred, rdonly, p, override)
1.54      augustss 3372:        struct vnode *vp;
1.1       cgd      3373:        int flags;
1.54      augustss 3374:        struct ucred *cred;
1.15      mycroft  3375:        int rdonly;
1.1       cgd      3376:        struct proc *p;
                   3377: {
                   3378:        struct vattr vattr;
                   3379:        int error;
                   3380:        if (flags & VWRITE) {
1.15      mycroft  3381:                /* Just vn_writechk() changed to check rdonly */
1.1       cgd      3382:                /*
                   3383:                 * Disallow write attempts on read-only file systems;
                   3384:                 * unless the file is a socket or a block or character
                   3385:                 * device resident on the file system.
                   3386:                 */
1.15      mycroft  3387:                if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
1.1       cgd      3388:                        switch (vp->v_type) {
1.23      fvdl     3389:                        case VREG:
                   3390:                        case VDIR:
                   3391:                        case VLNK:
1.1       cgd      3392:                                return (EROFS);
1.23      fvdl     3393:                        default:
1.22      christos 3394:                                break;
1.1       cgd      3395:                        }
                   3396:                }
                   3397:                /*
                   3398:                 * If there's shared text associated with
                   3399:                 * the inode, try to free it up once.  If
                   3400:                 * we fail, we can't allow writing.
                   3401:                 */
1.40      mrg      3402:                if ((vp->v_flag & VTEXT) && !uvm_vnp_uncache(vp))
                   3403:                        return (ETXTBSY);
1.1       cgd      3404:        }
1.23      fvdl     3405:        error = VOP_GETATTR(vp, &vattr, cred, p);
                   3406:        if (error)
1.1       cgd      3407:                return (error);
1.27      fvdl     3408:        error = VOP_ACCESS(vp, flags, cred, p);
                   3409:        /*
                   3410:         * Allow certain operations for the owner (reads and writes
                   3411:         * on files that are already open).
                   3412:         */
1.31      fvdl     3413:        if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
1.27      fvdl     3414:                error = 0;
                   3415:        return error;
1.1       cgd      3416: }

CVSweb <webmaster@jp.NetBSD.org>