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