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