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