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