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.34 (Berkeley) 02/21/91 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 len -= uiop->uio_resid; 391 if (len > 0) { 392 tlen = nfsm_rndup(len); 393 if (cnt != tlen || tlen != len) 394 nfsm_adj(m3, cnt-tlen, tlen-len); 395 } else { 396 m_freem(m3); 397 m3 = (struct mbuf *)0; 398 } 399 nfsm_build(p, u_long *, NFSX_UNSIGNED); 400 *p = txdr_unsigned(len); 401 mb->m_next = m3; 402 nfsm_srvdone; 403 } 404 405 /* 406 * nfs write service 407 */ 408 nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat) 409 struct mbuf *mrep, *md, **mrq; 410 caddr_t dpos; 411 struct ucred *cred; 412 u_long xid; 413 int *repstat; 414 { 415 register struct iovec *ivp; 416 register struct mbuf *mp; 417 register struct nfsv2_fattr *fp; 418 struct iovec iv[NFS_MAXIOVEC]; 419 struct vattr va; 420 register struct vattr *vap = &va; 421 register u_long *p; 422 register long t1; 423 caddr_t bpos; 424 int error = 0; 425 char *cp2; 426 struct mbuf *mb, *mb2, *mreq; 427 struct vnode *vp; 428 nfsv2fh_t nfh; 429 fhandle_t *fhp; 430 struct uio io, *uiop = &io; 431 off_t off; 432 long siz, len, xfer; 433 434 fhp = &nfh.fh_generic; 435 nfsm_srvmtofh(fhp); 436 nfsm_disect(p, u_long *, 4*NFSX_UNSIGNED); 437 off = fxdr_unsigned(off_t, *++p); 438 p += 2; 439 len = fxdr_unsigned(long, *p); 440 if (len > NFS_MAXDATA || len <= 0) { 441 error = EBADRPC; 442 nfsm_reply(0); 443 } 444 if (dpos == (mtod(md, caddr_t)+md->m_len)) { 445 mp = md->m_next; 446 if (mp == NULL) { 447 error = EBADRPC; 448 nfsm_reply(0); 449 } 450 } else { 451 mp = md; 452 siz = dpos-mtod(mp, caddr_t); 453 mp->m_len -= siz; 454 NFSMADV(mp, siz); 455 } 456 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 457 nfsm_reply(0); 458 if (error = nfsrv_access(vp, VWRITE, cred)) { 459 vput(vp); 460 nfsm_reply(0); 461 } 462 uiop->uio_resid = 0; 463 uiop->uio_rw = UIO_WRITE; 464 uiop->uio_segflg = UIO_SYSSPACE; 465 /* 466 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the 467 * loop until done. 468 */ 469 while (len > 0 && uiop->uio_resid == 0) { 470 ivp = iv; 471 siz = 0; 472 uiop->uio_iov = ivp; 473 uiop->uio_iovcnt = 0; 474 uiop->uio_offset = off; 475 while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) { 476 ivp->iov_base = mtod(mp, caddr_t); 477 if (len < mp->m_len) 478 ivp->iov_len = xfer = len; 479 else 480 ivp->iov_len = xfer = mp->m_len; 481 #ifdef notdef 482 /* Not Yet .. */ 483 if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0) 484 ivp->iov_op = NULL; /* what should it be ?? */ 485 else 486 ivp->iov_op = NULL; 487 #endif 488 uiop->uio_iovcnt++; 489 ivp++; 490 len -= xfer; 491 siz += xfer; 492 mp = mp->m_next; 493 } 494 if (len > 0 && mp == NULL) { 495 error = EBADRPC; 496 vput(vp); 497 nfsm_reply(0); 498 } 499 uiop->uio_resid = siz; 500 if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED, 501 cred)) { 502 vput(vp); 503 nfsm_reply(0); 504 } 505 off = uiop->uio_offset; 506 } 507 error = VOP_GETATTR(vp, vap, cred); 508 vput(vp); 509 nfsm_reply(NFSX_FATTR); 510 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 511 nfsm_srvfillattr; 512 nfsm_srvdone; 513 } 514 515 /* 516 * nfs create service 517 * now does a truncate to 0 length via. setattr if it already exists 518 */ 519 nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat) 520 struct mbuf *mrep, *md, **mrq; 521 caddr_t dpos; 522 struct ucred *cred; 523 u_long xid; 524 int *repstat; 525 { 526 register struct nfsv2_fattr *fp; 527 struct vattr va; 528 register struct vattr *vap = &va; 529 struct nameidata nami; 530 register struct nameidata *ndp = &nami; 531 register caddr_t cp; 532 register u_long *p; 533 register long t1; 534 caddr_t bpos; 535 long rdev; 536 int error = 0; 537 char *cp2; 538 struct mbuf *mb, *mb2, *mreq; 539 struct vnode *vp; 540 nfsv2fh_t nfh; 541 fhandle_t *fhp; 542 long len; 543 544 ndinit(ndp); 545 fhp = &nfh.fh_generic; 546 nfsm_srvmtofh(fhp); 547 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 548 ndp->ni_cred = cred; 549 ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 550 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 551 nfsm_reply(0); 552 VATTR_NULL(vap); 553 nfsm_disect(p, u_long *, NFSX_SATTR); 554 /* 555 * Iff doesn't exist, create it 556 * otherwise just truncate to 0 length 557 * should I set the mode too ?? 558 */ 559 if (ndp->ni_vp == NULL) { 560 vap->va_type = IFTOVT(fxdr_unsigned(u_long, *p)); 561 if (vap->va_type == VNON) 562 vap->va_type = VREG; 563 vap->va_mode = nfstov_mode(*p); 564 rdev = fxdr_unsigned(long, *(p+3)); 565 if (vap->va_type == VREG) { 566 if (error = VOP_CREATE(ndp, vap)) 567 nfsm_reply(0); 568 } else if (vap->va_type == VCHR || vap->va_type == VBLK || 569 vap->va_type == VFIFO) { 570 if (vap->va_type == VCHR && rdev == 0xffffffff) 571 vap->va_type = VFIFO; 572 if (vap->va_type == VFIFO) { 573 #ifndef FIFO 574 VOP_ABORTOP(ndp); 575 vput(ndp->ni_dvp); 576 error = ENXIO; 577 nfsm_reply(0); 578 #endif /* FIFO */ 579 } else if (error = suser(cred, (short *)0)) { 580 VOP_ABORTOP(ndp); 581 vput(ndp->ni_dvp); 582 nfsm_reply(0); 583 } else 584 vap->va_rdev = (dev_t)rdev; 585 if (error = VOP_MKNOD(ndp, vap, cred)) 586 nfsm_reply(0); 587 ndp->ni_nameiop = LOOKUP | LOCKLEAF | HASBUF; 588 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 589 nfsm_reply(0); 590 } else { 591 VOP_ABORTOP(ndp); 592 vput(ndp->ni_dvp); 593 error = ENXIO; 594 nfsm_reply(0); 595 } 596 vp = ndp->ni_vp; 597 } else { 598 vp = ndp->ni_vp; 599 ndp->ni_vp = NULLVP; 600 VOP_ABORTOP(ndp); 601 if (ndp->ni_dvp == vp) 602 vrele(ndp->ni_dvp); 603 else 604 vput(ndp->ni_dvp); 605 vap->va_size = 0; 606 if (error = VOP_SETATTR(vp, vap, cred)) { 607 vput(vp); 608 nfsm_reply(0); 609 } 610 } 611 bzero((caddr_t)fhp, sizeof(nfh)); 612 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 613 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 614 vput(vp); 615 nfsm_reply(0); 616 } 617 error = VOP_GETATTR(vp, vap, cred); 618 vput(vp); 619 nfsm_reply(NFSX_FH+NFSX_FATTR); 620 nfsm_srvfhtom(fhp); 621 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 622 nfsm_srvfillattr; 623 return (error); 624 nfsmout: 625 VOP_ABORTOP(ndp); 626 if (ndp->ni_dvp == ndp->ni_vp) 627 vrele(ndp->ni_dvp); 628 else 629 vput(ndp->ni_dvp); 630 if (ndp->ni_vp) 631 vput(ndp->ni_vp); 632 return (error); 633 } 634 635 /* 636 * nfs remove service 637 */ 638 nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat) 639 struct mbuf *mrep, *md, **mrq; 640 caddr_t dpos; 641 struct ucred *cred; 642 u_long xid; 643 int *repstat; 644 { 645 struct nameidata nami; 646 register struct nameidata *ndp = &nami; 647 register u_long *p; 648 register long t1; 649 caddr_t bpos; 650 int error = 0; 651 char *cp2; 652 struct mbuf *mb, *mreq; 653 struct vnode *vp; 654 nfsv2fh_t nfh; 655 fhandle_t *fhp; 656 long len; 657 658 ndinit(ndp); 659 fhp = &nfh.fh_generic; 660 nfsm_srvmtofh(fhp); 661 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 662 ndp->ni_cred = cred; 663 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 664 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 665 nfsm_reply(0); 666 vp = ndp->ni_vp; 667 if (vp->v_type == VDIR && 668 (error = suser(cred, (short *)0))) 669 goto out; 670 /* 671 * Don't unlink a mounted file. 672 */ 673 if (vp->v_flag & VROOT) { 674 error = EBUSY; 675 goto out; 676 } 677 if (vp->v_flag & VTEXT) 678 #ifdef NVM 679 (void) vnode_pager_uncache(vp); 680 #else 681 xrele(vp); /* try once to free text */ 682 #endif 683 out: 684 if (!error) { 685 error = VOP_REMOVE(ndp); 686 } else { 687 VOP_ABORTOP(ndp); 688 if (ndp->ni_dvp == vp) 689 vrele(ndp->ni_dvp); 690 else 691 vput(ndp->ni_dvp); 692 vput(vp); 693 } 694 nfsm_reply(0); 695 nfsm_srvdone; 696 } 697 698 /* 699 * nfs rename service 700 */ 701 nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat) 702 struct mbuf *mrep, *md, **mrq; 703 caddr_t dpos; 704 struct ucred *cred; 705 u_long xid; 706 int *repstat; 707 { 708 register struct nameidata *ndp; 709 register u_long *p; 710 register long t1; 711 caddr_t bpos; 712 int error = 0; 713 char *cp2; 714 struct mbuf *mb, *mreq; 715 struct nameidata nami, tond; 716 struct vnode *fvp, *tvp, *tdvp; 717 nfsv2fh_t fnfh, tnfh; 718 fhandle_t *ffhp, *tfhp; 719 long len, len2; 720 int rootflg = 0; 721 722 ndp = &nami; 723 ndinit(ndp); 724 ffhp = &fnfh.fh_generic; 725 tfhp = &tnfh.fh_generic; 726 nfsm_srvmtofh(ffhp); 727 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 728 /* 729 * Remember if we are root so that we can reset cr_uid before 730 * the second nfs_namei() call 731 */ 732 if (cred->cr_uid == 0) 733 rootflg++; 734 ndp->ni_cred = cred; 735 ndp->ni_nameiop = DELETE | WANTPARENT | SAVESTARTDIR; 736 if (error = nfs_namei(ndp, ffhp, len, &md, &dpos)) 737 nfsm_reply(0); 738 fvp = ndp->ni_vp; 739 nfsm_srvmtofh(tfhp); 740 nfsm_strsiz(len2, NFS_MAXNAMLEN); 741 if (rootflg) 742 cred->cr_uid = 0; 743 ndinit(&tond); 744 crhold(cred); 745 tond.ni_cred = cred; 746 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE 747 | SAVESTARTDIR; 748 if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos)) { 749 VOP_ABORTOP(ndp); 750 vrele(ndp->ni_dvp); 751 vrele(fvp); 752 goto out1; 753 } 754 tdvp = tond.ni_dvp; 755 tvp = tond.ni_vp; 756 if (tvp != NULL) { 757 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 758 error = EISDIR; 759 goto out; 760 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 761 error = ENOTDIR; 762 goto out; 763 } 764 } 765 if (fvp->v_mount != tdvp->v_mount) { 766 error = EXDEV; 767 goto out; 768 } 769 if (fvp == tdvp || fvp == tvp) 770 error = EINVAL; 771 out: 772 if (!error) { 773 error = VOP_RENAME(ndp, &tond); 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 vrele(tond.ni_startdir); 787 out1: 788 vrele(ndp->ni_startdir); 789 crfree(cred); 790 nfsm_reply(0); 791 return (error); 792 nfsmout: 793 if (ndp->ni_nameiop & SAVESTARTDIR) 794 vrele(ndp->ni_startdir); 795 VOP_ABORTOP(ndp); 796 vrele(ndp->ni_dvp); 797 vrele(fvp); 798 return (error); 799 } 800 801 /* 802 * nfs link service 803 */ 804 nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat) 805 struct mbuf *mrep, *md, **mrq; 806 caddr_t dpos; 807 struct ucred *cred; 808 u_long xid; 809 int *repstat; 810 { 811 struct nameidata nami; 812 register struct nameidata *ndp = &nami; 813 register u_long *p; 814 register long t1; 815 caddr_t bpos; 816 int error = 0; 817 char *cp2; 818 struct mbuf *mb, *mreq; 819 struct vnode *vp, *xp; 820 nfsv2fh_t nfh, dnfh; 821 fhandle_t *fhp, *dfhp; 822 long len; 823 824 ndinit(ndp); 825 fhp = &nfh.fh_generic; 826 dfhp = &dnfh.fh_generic; 827 nfsm_srvmtofh(fhp); 828 nfsm_srvmtofh(dfhp); 829 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 830 if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred)) 831 nfsm_reply(0); 832 if (vp->v_type == VDIR && (error = suser(cred, NULL))) 833 goto out1; 834 ndp->ni_cred = cred; 835 ndp->ni_nameiop = CREATE | LOCKPARENT; 836 if (error = nfs_namei(ndp, dfhp, len, &md, &dpos)) 837 goto out1; 838 xp = ndp->ni_vp; 839 if (xp != NULL) { 840 error = EEXIST; 841 goto out; 842 } 843 xp = ndp->ni_dvp; 844 if (vp->v_mount != xp->v_mount) 845 error = EXDEV; 846 out: 847 if (!error) { 848 error = VOP_LINK(vp, ndp); 849 } else { 850 VOP_ABORTOP(ndp); 851 if (ndp->ni_dvp == ndp->ni_vp) 852 vrele(ndp->ni_dvp); 853 else 854 vput(ndp->ni_dvp); 855 if (ndp->ni_vp) 856 vrele(ndp->ni_vp); 857 } 858 out1: 859 vrele(vp); 860 nfsm_reply(0); 861 nfsm_srvdone; 862 } 863 864 /* 865 * nfs symbolic link service 866 */ 867 nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat) 868 struct mbuf *mrep, *md, **mrq; 869 caddr_t dpos; 870 struct ucred *cred; 871 u_long xid; 872 int *repstat; 873 { 874 struct vattr va; 875 struct nameidata nami; 876 register struct nameidata *ndp = &nami; 877 register struct vattr *vap = &va; 878 register u_long *p; 879 register long t1; 880 struct nfsv2_sattr *sp; 881 caddr_t bpos; 882 struct uio io; 883 struct iovec iv; 884 int error = 0; 885 char *pathcp, *cp2; 886 struct mbuf *mb, *mreq; 887 nfsv2fh_t nfh; 888 fhandle_t *fhp; 889 long len, len2; 890 891 pathcp = (char *)0; 892 ndinit(ndp); 893 fhp = &nfh.fh_generic; 894 nfsm_srvmtofh(fhp); 895 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 896 ndp->ni_cred = cred; 897 ndp->ni_nameiop = CREATE | LOCKPARENT; 898 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 899 goto out; 900 nfsm_strsiz(len2, NFS_MAXPATHLEN); 901 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 902 iv.iov_base = pathcp; 903 iv.iov_len = len2; 904 io.uio_resid = len2; 905 io.uio_offset = 0; 906 io.uio_iov = &iv; 907 io.uio_iovcnt = 1; 908 io.uio_segflg = UIO_SYSSPACE; 909 io.uio_rw = UIO_READ; 910 nfsm_mtouio(&io, len2); 911 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); 912 *(pathcp + len2) = '\0'; 913 if (ndp->ni_vp) { 914 VOP_ABORTOP(ndp); 915 if (ndp->ni_dvp == ndp->ni_vp) 916 vrele(ndp->ni_dvp); 917 else 918 vput(ndp->ni_dvp); 919 vrele(ndp->ni_vp); 920 error = EEXIST; 921 goto out; 922 } 923 VATTR_NULL(vap); 924 vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode); 925 error = VOP_SYMLINK(ndp, vap, pathcp); 926 out: 927 if (pathcp) 928 FREE(pathcp, M_TEMP); 929 nfsm_reply(0); 930 return (error); 931 nfsmout: 932 VOP_ABORTOP(ndp); 933 if (ndp->ni_dvp == ndp->ni_vp) 934 vrele(ndp->ni_dvp); 935 else 936 vput(ndp->ni_dvp); 937 if (ndp->ni_vp); 938 vrele(ndp->ni_vp); 939 if (pathcp) 940 FREE(pathcp, M_TEMP); 941 return (error); 942 } 943 944 /* 945 * nfs mkdir service 946 */ 947 nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat) 948 struct mbuf *mrep, *md, **mrq; 949 caddr_t dpos; 950 struct ucred *cred; 951 u_long xid; 952 int *repstat; 953 { 954 struct vattr va; 955 register struct vattr *vap = &va; 956 register struct nfsv2_fattr *fp; 957 struct nameidata nami; 958 register struct nameidata *ndp = &nami; 959 register caddr_t cp; 960 register u_long *p; 961 register long t1; 962 caddr_t bpos; 963 int error = 0; 964 char *cp2; 965 struct mbuf *mb, *mb2, *mreq; 966 struct vnode *vp; 967 nfsv2fh_t nfh; 968 fhandle_t *fhp; 969 long len; 970 971 ndinit(ndp); 972 fhp = &nfh.fh_generic; 973 nfsm_srvmtofh(fhp); 974 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 975 ndp->ni_cred = cred; 976 ndp->ni_nameiop = CREATE | LOCKPARENT | SAVESTARTDIR; 977 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 978 nfsm_reply(0); 979 nfsm_disect(p, u_long *, NFSX_UNSIGNED); 980 VATTR_NULL(vap); 981 vap->va_type = VDIR; 982 vap->va_mode = nfstov_mode(*p++); 983 vp = ndp->ni_vp; 984 if (vp != NULL) { 985 VOP_ABORTOP(ndp); 986 if (ndp->ni_dvp == vp) 987 vrele(ndp->ni_dvp); 988 else 989 vput(ndp->ni_dvp); 990 vrele(vp); 991 vrele(ndp->ni_startdir); 992 error = EEXIST; 993 nfsm_reply(0); 994 } 995 error = VOP_MKDIR(ndp, vap); 996 vrele(ndp->ni_startdir); 997 if (error) 998 nfsm_reply(0); 999 vp = ndp->ni_vp; 1000 bzero((caddr_t)fhp, sizeof(nfh)); 1001 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1002 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 1003 vput(vp); 1004 nfsm_reply(0); 1005 } 1006 error = VOP_GETATTR(vp, vap, cred); 1007 vput(vp); 1008 nfsm_reply(NFSX_FH+NFSX_FATTR); 1009 nfsm_srvfhtom(fhp); 1010 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 1011 nfsm_srvfillattr; 1012 return (error); 1013 nfsmout: 1014 VOP_ABORTOP(ndp); 1015 if (ndp->ni_dvp == ndp->ni_vp) 1016 vrele(ndp->ni_dvp); 1017 else 1018 vput(ndp->ni_dvp); 1019 if (ndp->ni_vp) 1020 vrele(ndp->ni_vp); 1021 return (error); 1022 } 1023 1024 /* 1025 * nfs rmdir service 1026 */ 1027 nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat) 1028 struct mbuf *mrep, *md, **mrq; 1029 caddr_t dpos; 1030 struct ucred *cred; 1031 u_long xid; 1032 int *repstat; 1033 { 1034 struct nameidata nami; 1035 register struct nameidata *ndp = &nami; 1036 register u_long *p; 1037 register long t1; 1038 caddr_t bpos; 1039 int error = 0; 1040 char *cp2; 1041 struct mbuf *mb, *mreq; 1042 struct vnode *vp; 1043 nfsv2fh_t nfh; 1044 fhandle_t *fhp; 1045 long len; 1046 1047 ndinit(ndp); 1048 fhp = &nfh.fh_generic; 1049 nfsm_srvmtofh(fhp); 1050 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1051 ndp->ni_cred = cred; 1052 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 1053 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 1054 nfsm_reply(0); 1055 vp = ndp->ni_vp; 1056 if (vp->v_type != VDIR) { 1057 error = ENOTDIR; 1058 goto out; 1059 } 1060 /* 1061 * No rmdir "." please. 1062 */ 1063 if (ndp->ni_dvp == vp) { 1064 error = EINVAL; 1065 goto out; 1066 } 1067 /* 1068 * Don't unlink a mounted file. 1069 */ 1070 if (vp->v_flag & VROOT) 1071 error = EBUSY; 1072 out: 1073 if (!error) { 1074 error = VOP_RMDIR(ndp); 1075 } else { 1076 VOP_ABORTOP(ndp); 1077 if (ndp->ni_dvp == ndp->ni_vp) 1078 vrele(ndp->ni_dvp); 1079 else 1080 vput(ndp->ni_dvp); 1081 vput(vp); 1082 } 1083 nfsm_reply(0); 1084 nfsm_srvdone; 1085 } 1086 1087 /* 1088 * nfs readdir service 1089 * - mallocs what it thinks is enough to read 1090 * count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR 1091 * - calls VOP_READDIR() 1092 * - loops around building the reply 1093 * if the output generated exceeds count break out of loop 1094 * The nfsm_clget macro is used here so that the reply will be packed 1095 * tightly in mbuf clusters. 1096 * - it only knows that it has encountered eof when the VOP_READDIR() 1097 * reads nothing 1098 * - as such one readdir rpc will return eof false although you are there 1099 * and then the next will return eof 1100 * - it trims out records with d_ino == 0 1101 * this doesn't matter for Unix clients, but they might confuse clients 1102 * for other os'. 1103 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 1104 * than requested, but this may not apply to all filesystems. For 1105 * example, client NFS does not { although it is never remote mounted 1106 * anyhow } 1107 * PS: The NFS protocol spec. does not clarify what the "count" byte 1108 * argument is a count of.. just name strings and file id's or the 1109 * entire reply rpc or ... 1110 * I tried just file name and id sizes and it confused the Sun client, 1111 * so I am using the full rpc size now. The "paranoia.." comment refers 1112 * to including the status longwords that are not a part of the dir. 1113 * "entry" structures, but are in the rpc. 1114 */ 1115 nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat) 1116 struct mbuf **mrq; 1117 struct mbuf *mrep, *md; 1118 caddr_t dpos; 1119 struct ucred *cred; 1120 u_long xid; 1121 int *repstat; 1122 { 1123 register char *bp, *be; 1124 register struct mbuf *mp; 1125 register struct direct *dp; 1126 register caddr_t cp; 1127 register u_long *p; 1128 register long t1; 1129 caddr_t bpos; 1130 int error = 0; 1131 char *cp2; 1132 struct mbuf *mb, *mb2, *mreq; 1133 char *cpos, *cend; 1134 int len, nlen, rem, xfer, tsiz, i; 1135 struct vnode *vp; 1136 struct mbuf *mp2, *mp3; 1137 nfsv2fh_t nfh; 1138 fhandle_t *fhp; 1139 struct uio io; 1140 struct iovec iv; 1141 int siz, cnt, fullsiz, eofflag; 1142 u_long on; 1143 char *rbuf; 1144 off_t off, toff; 1145 1146 fhp = &nfh.fh_generic; 1147 nfsm_srvmtofh(fhp); 1148 nfsm_disect(p, u_long *, 2*NFSX_UNSIGNED); 1149 toff = fxdr_unsigned(off_t, *p++); 1150 off = (toff & ~(DIRBLKSIZ-1)); 1151 on = (toff & (DIRBLKSIZ-1)); 1152 cnt = fxdr_unsigned(int, *p); 1153 siz = ((cnt+DIRBLKSIZ-1) & ~(DIRBLKSIZ-1)); 1154 if (cnt > NFS_MAXREADDIR) 1155 siz = NFS_MAXREADDIR; 1156 fullsiz = siz; 1157 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1158 nfsm_reply(0); 1159 if (error = nfsrv_access(vp, VEXEC, cred)) { 1160 vput(vp); 1161 nfsm_reply(0); 1162 } 1163 VOP_UNLOCK(vp); 1164 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1165 again: 1166 iv.iov_base = rbuf; 1167 iv.iov_len = fullsiz; 1168 io.uio_iov = &iv; 1169 io.uio_iovcnt = 1; 1170 io.uio_offset = off; 1171 io.uio_resid = fullsiz; 1172 io.uio_segflg = UIO_SYSSPACE; 1173 io.uio_rw = UIO_READ; 1174 error = VOP_READDIR(vp, &io, cred, &eofflag); 1175 off = io.uio_offset; 1176 if (error) { 1177 vrele(vp); 1178 free((caddr_t)rbuf, M_TEMP); 1179 nfsm_reply(0); 1180 } 1181 if (io.uio_resid) { 1182 siz -= io.uio_resid; 1183 1184 /* 1185 * If nothing read, return eof 1186 * rpc reply 1187 */ 1188 if (siz == 0) { 1189 vrele(vp); 1190 nfsm_reply(2*NFSX_UNSIGNED); 1191 nfsm_build(p, u_long *, 2*NFSX_UNSIGNED); 1192 *p++ = nfs_false; 1193 *p = nfs_true; 1194 FREE((caddr_t)rbuf, M_TEMP); 1195 return (0); 1196 } 1197 } 1198 1199 /* 1200 * Check for degenerate cases of nothing useful read. 1201 * If so go try again 1202 */ 1203 cpos = rbuf + on; 1204 cend = rbuf + siz; 1205 dp = (struct direct *)cpos; 1206 while (cpos < cend && dp->d_ino == 0) { 1207 cpos += dp->d_reclen; 1208 dp = (struct direct *)cpos; 1209 } 1210 if (cpos >= cend) { 1211 toff = off; 1212 siz = fullsiz; 1213 on = 0; 1214 goto again; 1215 } 1216 1217 cpos = rbuf + on; 1218 cend = rbuf + siz; 1219 dp = (struct direct *)cpos; 1220 vrele(vp); 1221 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 1222 bp = be = (caddr_t)0; 1223 mp3 = (struct mbuf *)0; 1224 nfsm_reply(siz); 1225 1226 /* Loop through the records and build reply */ 1227 while (cpos < cend) { 1228 if (dp->d_ino != 0) { 1229 nlen = dp->d_namlen; 1230 rem = nfsm_rndup(nlen)-nlen; 1231 1232 /* 1233 * As noted above, the NFS spec. is not clear about what 1234 * should be included in "count" as totalled up here in 1235 * "len". 1236 */ 1237 len += (4*NFSX_UNSIGNED+nlen+rem); 1238 if (len > cnt) { 1239 eofflag = 0; 1240 break; 1241 } 1242 1243 /* Build the directory record xdr from the direct entry */ 1244 nfsm_clget; 1245 *p = nfs_true; 1246 bp += NFSX_UNSIGNED; 1247 nfsm_clget; 1248 *p = txdr_unsigned(dp->d_ino); 1249 bp += NFSX_UNSIGNED; 1250 nfsm_clget; 1251 *p = txdr_unsigned(nlen); 1252 bp += NFSX_UNSIGNED; 1253 1254 /* And loop arround copying the name */ 1255 xfer = nlen; 1256 cp = dp->d_name; 1257 while (xfer > 0) { 1258 nfsm_clget; 1259 if ((bp+xfer) > be) 1260 tsiz = be-bp; 1261 else 1262 tsiz = xfer; 1263 bcopy(cp, bp, tsiz); 1264 bp += tsiz; 1265 xfer -= tsiz; 1266 if (xfer > 0) 1267 cp += tsiz; 1268 } 1269 /* And null pad to a long boundary */ 1270 for (i = 0; i < rem; i++) 1271 *bp++ = '\0'; 1272 nfsm_clget; 1273 1274 /* Finish off the record */ 1275 toff += dp->d_reclen; 1276 *p = txdr_unsigned(toff); 1277 bp += NFSX_UNSIGNED; 1278 } else 1279 toff += dp->d_reclen; 1280 cpos += dp->d_reclen; 1281 dp = (struct direct *)cpos; 1282 } 1283 nfsm_clget; 1284 *p = nfs_false; 1285 bp += NFSX_UNSIGNED; 1286 nfsm_clget; 1287 if (eofflag) 1288 *p = nfs_true; 1289 else 1290 *p = nfs_false; 1291 bp += NFSX_UNSIGNED; 1292 if (bp < be) 1293 mp->m_len = bp-mtod(mp, caddr_t); 1294 mb->m_next = mp3; 1295 FREE(rbuf, M_TEMP); 1296 nfsm_srvdone; 1297 } 1298 1299 /* 1300 * nfs statfs service 1301 */ 1302 nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat) 1303 struct mbuf **mrq; 1304 struct mbuf *mrep, *md; 1305 caddr_t dpos; 1306 struct ucred *cred; 1307 u_long xid; 1308 int *repstat; 1309 { 1310 register struct statfs *sf; 1311 register struct nfsv2_statfs *sfp; 1312 register u_long *p; 1313 register long t1; 1314 caddr_t bpos; 1315 int error = 0; 1316 char *cp2; 1317 struct mbuf *mb, *mb2, *mreq; 1318 struct vnode *vp; 1319 nfsv2fh_t nfh; 1320 fhandle_t *fhp; 1321 struct statfs statfs; 1322 1323 fhp = &nfh.fh_generic; 1324 nfsm_srvmtofh(fhp); 1325 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1326 nfsm_reply(0); 1327 sf = &statfs; 1328 error = VFS_STATFS(vp->v_mount, sf); 1329 vput(vp); 1330 nfsm_reply(NFSX_STATFS); 1331 nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS); 1332 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 1333 sfp->sf_bsize = txdr_unsigned(sf->f_fsize); 1334 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 1335 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 1336 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 1337 nfsm_srvdone; 1338 } 1339 1340 /* 1341 * Null operation, used by clients to ping server 1342 */ 1343 /* ARGSUSED */ 1344 nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat) 1345 struct mbuf **mrq; 1346 struct mbuf *mrep, *md; 1347 caddr_t dpos; 1348 struct ucred *cred; 1349 u_long xid; 1350 int *repstat; 1351 { 1352 caddr_t bpos; 1353 int error = 0; 1354 struct mbuf *mb, *mreq; 1355 1356 error = VNOVAL; 1357 nfsm_reply(0); 1358 return (error); 1359 } 1360 1361 /* 1362 * No operation, used for obsolete procedures 1363 */ 1364 /* ARGSUSED */ 1365 nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat) 1366 struct mbuf **mrq; 1367 struct mbuf *mrep, *md; 1368 caddr_t dpos; 1369 struct ucred *cred; 1370 u_long xid; 1371 int *repstat; 1372 { 1373 caddr_t bpos; 1374 int error = 0; 1375 struct mbuf *mb, *mreq; 1376 1377 error = EPROCUNAVAIL; 1378 nfsm_reply(0); 1379 return (error); 1380 } 1381 1382 /* 1383 * Perform access checking for vnodes obtained from file handles that would 1384 * refer to files already opened by a Unix client. You cannot just use 1385 * vn_writechk() and VOP_ACCESS() for two reasons. 1386 * 1 - You must check for MNT_EXRDONLY as well as MNT_RDONLY for the write case 1387 * 2 - The owner is to be given access irrespective of mode bits so that 1388 * processes that chmod after opening a file don't break. I don't like 1389 * this because it opens a security hole, but since the nfs server opens 1390 * a security hole the size of a barn door anyhow, what the heck. 1391 */ 1392 nfsrv_access(vp, flags, cred) 1393 register struct vnode *vp; 1394 int flags; 1395 register struct ucred *cred; 1396 { 1397 struct vattr vattr; 1398 int error; 1399 if (flags & VWRITE) { 1400 /* Just vn_writechk() changed to check MNT_EXRDONLY */ 1401 /* 1402 * Disallow write attempts on read-only file systems; 1403 * unless the file is a socket or a block or character 1404 * device resident on the file system. 1405 */ 1406 if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) { 1407 switch (vp->v_type) { 1408 case VREG: case VDIR: case VLNK: 1409 return (EROFS); 1410 } 1411 } 1412 /* 1413 * If there's shared text associated with 1414 * the inode, try to free it up once. If 1415 * we fail, we can't allow writing. 1416 */ 1417 #ifdef NVM 1418 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 1419 return (ETXTBSY); 1420 #else 1421 if (vp->v_flag & VTEXT) 1422 xrele(vp); 1423 if (vp->v_flag & VTEXT) 1424 return (ETXTBSY); 1425 #endif 1426 } 1427 if (error = VOP_GETATTR(vp, &vattr, cred)) 1428 return (error); 1429 if ((error = VOP_ACCESS(vp, flags, cred)) && 1430 cred->cr_uid != vattr.va_uid) 1431 return (error); 1432 return (0); 1433 } 1434