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.60 (Berkeley) 09/30/92 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 <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/proc.h> 34 #include <sys/file.h> 35 #include <sys/namei.h> 36 #include <sys/vnode.h> 37 #include <sys/mount.h> 38 #include <sys/mbuf.h> 39 #include <sys/dirent.h> 40 #include <sys/stat.h> 41 42 #include <vm/vm.h> 43 44 #include <nfs/nfsv2.h> 45 #include <nfs/rpcv2.h> 46 #include <nfs/nfs.h> 47 #include <nfs/xdr_subs.h> 48 #include <nfs/nfsm_subs.h> 49 #include <nfs/nqnfs.h> 50 51 /* Defs */ 52 #define TRUE 1 53 #define FALSE 0 54 55 /* Global vars */ 56 extern u_long nfs_procids[NFS_NPROCS]; 57 extern u_long nfs_xdrneg1; 58 extern u_long nfs_false, nfs_true; 59 nfstype nfs_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, 60 NFCHR, NFNON }; 61 62 /* 63 * nqnfs access service 64 */ 65 nqnfsrv_access(nfsd, mrep, md, dpos, cred, nam, mrq) 66 struct nfsd *nfsd; 67 struct mbuf *mrep, *md; 68 caddr_t dpos; 69 struct ucred *cred; 70 struct mbuf *nam, **mrq; 71 { 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, rdonly, cache, mode = 0; 79 char *cp2; 80 struct mbuf *mb, *mb2, *mreq; 81 u_quad_t frev; 82 83 fhp = &nfh.fh_generic; 84 nfsm_srvmtofh(fhp); 85 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 86 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 87 nfsm_reply(0); 88 if (*tl++ == nfs_true) 89 mode |= VREAD; 90 if (*tl++ == nfs_true) 91 mode |= VWRITE; 92 if (*tl == nfs_true) 93 mode |= VEXEC; 94 error = nfsrv_access(vp, mode, cred, rdonly, nfsd->nd_procp); 95 vput(vp); 96 nfsm_reply(0); 97 nfsm_srvdone; 98 } 99 100 /* 101 * nfs getattr service 102 */ 103 nfsrv_getattr(nfsd, mrep, md, dpos, cred, nam, mrq) 104 struct nfsd *nfsd; 105 struct mbuf *mrep, *md; 106 caddr_t dpos; 107 struct ucred *cred; 108 struct mbuf *nam, **mrq; 109 { 110 register struct nfsv2_fattr *fp; 111 struct vattr va; 112 register struct vattr *vap = &va; 113 struct vnode *vp; 114 nfsv2fh_t nfh; 115 fhandle_t *fhp; 116 register u_long *tl; 117 register long t1; 118 caddr_t bpos; 119 int error = 0, rdonly, cache; 120 char *cp2; 121 struct mbuf *mb, *mb2, *mreq; 122 u_quad_t frev; 123 124 fhp = &nfh.fh_generic; 125 nfsm_srvmtofh(fhp); 126 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 127 nfsm_reply(0); 128 nqsrv_getl(vp, NQL_READ); 129 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp); 130 vput(vp); 131 nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 132 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 133 nfsm_srvfillattr; 134 nfsm_srvdone; 135 } 136 137 /* 138 * nfs setattr service 139 */ 140 nfsrv_setattr(nfsd, mrep, md, dpos, cred, nam, mrq) 141 struct nfsd *nfsd; 142 struct mbuf *mrep, *md; 143 caddr_t dpos; 144 struct ucred *cred; 145 struct mbuf *nam, **mrq; 146 { 147 struct vattr va; 148 register struct vattr *vap = &va; 149 register struct nfsv2_sattr *sp; 150 register struct nfsv2_fattr *fp; 151 struct vnode *vp; 152 nfsv2fh_t nfh; 153 fhandle_t *fhp; 154 register u_long *tl; 155 register long t1; 156 caddr_t bpos; 157 int error = 0, rdonly, cache, duration2, cache2; 158 char *cp2; 159 struct mbuf *mb, *mb2, *mreq; 160 u_quad_t frev, frev2; 161 162 fhp = &nfh.fh_generic; 163 nfsm_srvmtofh(fhp); 164 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 165 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 166 nfsm_reply(0); 167 nqsrv_getl(vp, NQL_WRITE); 168 if (error = nfsrv_access(vp, VWRITE, cred, rdonly, nfsd->nd_procp)) 169 goto out; 170 VATTR_NULL(vap); 171 /* 172 * Nah nah nah nah na nah 173 * There is a bug in the Sun client that puts 0xffff in the mode 174 * field of sattr when it should put in 0xffffffff. The u_short 175 * doesn't sign extend. 176 * --> check the low order 2 bytes for 0xffff 177 */ 178 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 179 vap->va_mode = nfstov_mode(sp->sa_mode); 180 if (sp->sa_uid != nfs_xdrneg1) 181 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid); 182 if (sp->sa_gid != nfs_xdrneg1) 183 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid); 184 if (nfsd->nd_nqlflag == NQL_NOVAL) { 185 if (sp->sa_nfssize != nfs_xdrneg1) 186 vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_nfssize); 187 /* 188 * The usec field of sa_atime is overloaded with the va_flags field 189 * for 4.4BSD clients. Hopefully other clients always set both the 190 * sec and usec fields to -1 when not setting the atime. 191 */ 192 if (sp->sa_nfsatime.nfs_sec != nfs_xdrneg1) { 193 vap->va_atime.ts_sec = fxdr_unsigned(long, sp->sa_nfsatime.nfs_sec); 194 vap->va_atime.ts_nsec = 0; 195 } 196 if (sp->sa_nfsatime.nfs_usec != nfs_xdrneg1) 197 vap->va_flags = fxdr_unsigned(u_long, sp->sa_nfsatime.nfs_usec); 198 if (sp->sa_nfsmtime.nfs_sec != nfs_xdrneg1) 199 fxdr_nfstime(&sp->sa_nfsmtime, &vap->va_mtime); 200 } else { 201 fxdr_hyper(&sp->sa_nqsize, &vap->va_size); 202 fxdr_nqtime(&sp->sa_nqatime, &vap->va_atime); 203 fxdr_nqtime(&sp->sa_nqmtime, &vap->va_mtime); 204 vap->va_flags = fxdr_unsigned(u_long, sp->sa_nqflags); 205 } 206 if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) { 207 vput(vp); 208 nfsm_reply(0); 209 } 210 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp); 211 out: 212 vput(vp); 213 nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 2*NFSX_UNSIGNED); 214 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 215 nfsm_srvfillattr; 216 if (nfsd->nd_nqlflag != NQL_NOVAL) { 217 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 218 txdr_hyper(&frev2, tl); 219 } 220 nfsm_srvdone; 221 } 222 223 /* 224 * nfs lookup rpc 225 */ 226 nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq) 227 struct nfsd *nfsd; 228 struct mbuf *mrep, *md; 229 caddr_t dpos; 230 struct ucred *cred; 231 struct mbuf *nam, **mrq; 232 { 233 register struct nfsv2_fattr *fp; 234 struct nameidata nd; 235 struct vnode *vp; 236 nfsv2fh_t nfh; 237 fhandle_t *fhp; 238 register caddr_t cp; 239 register u_long *tl; 240 register long t1; 241 caddr_t bpos; 242 int error = 0, rdonly, cache, duration2, cache2, len; 243 char *cp2; 244 struct mbuf *mb, *mb2, *mreq; 245 struct vattr va, *vap = &va; 246 u_quad_t frev, frev2; 247 248 fhp = &nfh.fh_generic; 249 if (nfsd->nd_nqlflag != NQL_NOVAL) { 250 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 251 duration2 = fxdr_unsigned(int, *tl); 252 } 253 nfsm_srvmtofh(fhp); 254 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 255 nd.ni_cnd.cn_cred = cred; 256 nd.ni_cnd.cn_nameiop = LOOKUP; 257 nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART; 258 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, 259 nfsd->nd_procp)) 260 nfsm_reply(0); 261 nqsrv_getl(nd.ni_startdir, NQL_READ); 262 vrele(nd.ni_startdir); 263 FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); 264 vp = nd.ni_vp; 265 bzero((caddr_t)fhp, sizeof(nfh)); 266 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 267 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 268 vput(vp); 269 nfsm_reply(0); 270 } 271 if (duration2) 272 (void) nqsrv_getlease(vp, &duration2, NQL_READ, nfsd, 273 nam, &cache2, &frev2, cred); 274 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp); 275 vput(vp); 276 nfsm_reply(NFSX_FH + NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 5*NFSX_UNSIGNED); 277 if (nfsd->nd_nqlflag != NQL_NOVAL) { 278 if (duration2) { 279 nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED); 280 *tl++ = txdr_unsigned(NQL_READ); 281 *tl++ = txdr_unsigned(cache2); 282 *tl++ = txdr_unsigned(duration2); 283 txdr_hyper(&frev2, tl); 284 } else { 285 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 286 *tl = 0; 287 } 288 } 289 nfsm_srvfhtom(fhp); 290 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 291 nfsm_srvfillattr; 292 nfsm_srvdone; 293 } 294 295 /* 296 * nfs readlink service 297 */ 298 nfsrv_readlink(nfsd, mrep, md, dpos, cred, nam, mrq) 299 struct nfsd *nfsd; 300 struct mbuf *mrep, *md; 301 caddr_t dpos; 302 struct ucred *cred; 303 struct mbuf *nam, **mrq; 304 { 305 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 306 register struct iovec *ivp = iv; 307 register struct mbuf *mp; 308 register u_long *tl; 309 register long t1; 310 caddr_t bpos; 311 int error = 0, rdonly, cache, i, tlen, len; 312 char *cp2; 313 struct mbuf *mb, *mb2, *mp2, *mp3, *mreq; 314 struct vnode *vp; 315 nfsv2fh_t nfh; 316 fhandle_t *fhp; 317 struct uio io, *uiop = &io; 318 u_quad_t frev; 319 320 fhp = &nfh.fh_generic; 321 nfsm_srvmtofh(fhp); 322 len = 0; 323 i = 0; 324 while (len < NFS_MAXPATHLEN) { 325 MGET(mp, M_WAIT, MT_DATA); 326 MCLGET(mp, M_WAIT); 327 mp->m_len = NFSMSIZ(mp); 328 if (len == 0) 329 mp3 = mp2 = mp; 330 else { 331 mp2->m_next = mp; 332 mp2 = mp; 333 } 334 if ((len+mp->m_len) > NFS_MAXPATHLEN) { 335 mp->m_len = NFS_MAXPATHLEN-len; 336 len = NFS_MAXPATHLEN; 337 } else 338 len += mp->m_len; 339 ivp->iov_base = mtod(mp, caddr_t); 340 ivp->iov_len = mp->m_len; 341 i++; 342 ivp++; 343 } 344 uiop->uio_iov = iv; 345 uiop->uio_iovcnt = i; 346 uiop->uio_offset = 0; 347 uiop->uio_resid = len; 348 uiop->uio_rw = UIO_READ; 349 uiop->uio_segflg = UIO_SYSSPACE; 350 uiop->uio_procp = (struct proc *)0; 351 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) { 352 m_freem(mp3); 353 nfsm_reply(0); 354 } 355 if (vp->v_type != VLNK) { 356 error = EINVAL; 357 goto out; 358 } 359 nqsrv_getl(vp, NQL_READ); 360 error = VOP_READLINK(vp, uiop, cred); 361 out: 362 vput(vp); 363 if (error) 364 m_freem(mp3); 365 nfsm_reply(NFSX_UNSIGNED); 366 if (uiop->uio_resid > 0) { 367 len -= uiop->uio_resid; 368 tlen = nfsm_rndup(len); 369 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len); 370 } 371 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 372 *tl = txdr_unsigned(len); 373 mb->m_next = mp3; 374 nfsm_srvdone; 375 } 376 377 /* 378 * nfs read service 379 */ 380 nfsrv_read(nfsd, mrep, md, dpos, cred, nam, mrq) 381 struct nfsd *nfsd; 382 struct mbuf *mrep, *md; 383 caddr_t dpos; 384 struct ucred *cred; 385 struct mbuf *nam, **mrq; 386 { 387 register struct iovec *iv; 388 struct iovec *iv2; 389 register struct mbuf *m; 390 register struct nfsv2_fattr *fp; 391 register u_long *tl; 392 register long t1; 393 caddr_t bpos; 394 int error = 0, rdonly, cache, i, cnt, len, left, siz, tlen; 395 char *cp2; 396 struct mbuf *mb, *mb2, *mreq; 397 struct mbuf *m2; 398 struct vnode *vp; 399 nfsv2fh_t nfh; 400 fhandle_t *fhp; 401 struct uio io, *uiop = &io; 402 struct vattr va, *vap = &va; 403 off_t off; 404 u_quad_t frev; 405 406 fhp = &nfh.fh_generic; 407 nfsm_srvmtofh(fhp); 408 if (nfsd->nd_nqlflag == NQL_NOVAL) { 409 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 410 off = (off_t)fxdr_unsigned(u_long, *tl); 411 } else { 412 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 413 fxdr_hyper(tl, &off); 414 } 415 nfsm_srvstrsiz(cnt, NFS_MAXDATA); 416 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 417 nfsm_reply(0); 418 nqsrv_getl(vp, NQL_READ); 419 if (error = nfsrv_access(vp, VREAD | VEXEC, cred, rdonly, nfsd->nd_procp)) { 420 vput(vp); 421 nfsm_reply(0); 422 } 423 if (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp)) { 424 vput(vp); 425 nfsm_reply(0); 426 } 427 if (off >= vap->va_size) 428 cnt = 0; 429 else if ((off + cnt) > vap->va_size) 430 cnt = nfsm_rndup(vap->va_size - off); 431 nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)+NFSX_UNSIGNED+nfsm_rndup(cnt)); 432 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 433 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 434 len = left = cnt; 435 if (cnt > 0) { 436 /* 437 * Generate the mbuf list with the uio_iov ref. to it. 438 */ 439 i = 0; 440 m = m2 = mb; 441 MALLOC(iv, struct iovec *, 442 ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec), 443 M_TEMP, M_WAITOK); 444 iv2 = iv; 445 while (left > 0) { 446 siz = min(M_TRAILINGSPACE(m), left); 447 if (siz > 0) { 448 m->m_len += siz; 449 iv->iov_base = bpos; 450 iv->iov_len = siz; 451 iv++; 452 i++; 453 left -= siz; 454 } 455 if (left > 0) { 456 MGET(m, M_WAIT, MT_DATA); 457 MCLGET(m, M_WAIT); 458 m->m_len = 0; 459 m2->m_next = m; 460 m2 = m; 461 bpos = mtod(m, caddr_t); 462 } 463 } 464 uiop->uio_iov = iv2; 465 uiop->uio_iovcnt = i; 466 uiop->uio_offset = off; 467 uiop->uio_resid = cnt; 468 uiop->uio_rw = UIO_READ; 469 uiop->uio_segflg = UIO_SYSSPACE; 470 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred); 471 off = uiop->uio_offset; 472 FREE((caddr_t)iv2, M_TEMP); 473 if (error || (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp))) { 474 m_freem(mreq); 475 vput(vp); 476 nfsm_reply(0); 477 } 478 } else 479 uiop->uio_resid = 0; 480 vput(vp); 481 nfsm_srvfillattr; 482 len -= uiop->uio_resid; 483 tlen = nfsm_rndup(len); 484 if (cnt != tlen || tlen != len) 485 nfsm_adj(mb, cnt-tlen, tlen-len); 486 *tl = txdr_unsigned(len); 487 nfsm_srvdone; 488 } 489 490 /* 491 * nfs write service 492 */ 493 nfsrv_write(nfsd, mrep, md, dpos, cred, nam, mrq) 494 struct nfsd *nfsd; 495 struct mbuf *mrep, *md; 496 caddr_t dpos; 497 struct ucred *cred; 498 struct mbuf *nam, **mrq; 499 { 500 register struct iovec *ivp; 501 register struct mbuf *mp; 502 register struct nfsv2_fattr *fp; 503 struct iovec iv[NFS_MAXIOVEC]; 504 struct vattr va; 505 register struct vattr *vap = &va; 506 register u_long *tl; 507 register long t1; 508 caddr_t bpos; 509 int error = 0, rdonly, cache, siz, len, xfer; 510 int ioflags = IO_SYNC | IO_NODELOCKED; 511 char *cp2; 512 struct mbuf *mb, *mb2, *mreq; 513 struct vnode *vp; 514 nfsv2fh_t nfh; 515 fhandle_t *fhp; 516 struct uio io, *uiop = &io; 517 off_t off; 518 u_quad_t frev; 519 520 fhp = &nfh.fh_generic; 521 nfsm_srvmtofh(fhp); 522 nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED); 523 if (nfsd->nd_nqlflag == NQL_NOVAL) { 524 off = (off_t)fxdr_unsigned(u_long, *++tl); 525 tl += 2; 526 } else { 527 fxdr_hyper(tl, &off); 528 tl += 2; 529 if (fxdr_unsigned(u_long, *tl++)) 530 ioflags |= IO_APPEND; 531 } 532 len = fxdr_unsigned(long, *tl); 533 if (len > NFS_MAXDATA || len <= 0) { 534 error = EBADRPC; 535 nfsm_reply(0); 536 } 537 if (dpos == (mtod(md, caddr_t)+md->m_len)) { 538 mp = md->m_next; 539 if (mp == NULL) { 540 error = EBADRPC; 541 nfsm_reply(0); 542 } 543 } else { 544 mp = md; 545 siz = dpos-mtod(mp, caddr_t); 546 mp->m_len -= siz; 547 NFSMADV(mp, siz); 548 } 549 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 550 nfsm_reply(0); 551 nqsrv_getl(vp, NQL_WRITE); 552 if (error = nfsrv_access(vp, VWRITE, cred, rdonly, nfsd->nd_procp)) { 553 vput(vp); 554 nfsm_reply(0); 555 } 556 uiop->uio_resid = 0; 557 uiop->uio_rw = UIO_WRITE; 558 uiop->uio_segflg = UIO_SYSSPACE; 559 uiop->uio_procp = (struct proc *)0; 560 /* 561 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the 562 * loop until done. 563 */ 564 while (len > 0 && uiop->uio_resid == 0) { 565 ivp = iv; 566 siz = 0; 567 uiop->uio_iov = ivp; 568 uiop->uio_iovcnt = 0; 569 uiop->uio_offset = off; 570 while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) { 571 ivp->iov_base = mtod(mp, caddr_t); 572 if (len < mp->m_len) 573 ivp->iov_len = xfer = len; 574 else 575 ivp->iov_len = xfer = mp->m_len; 576 #ifdef notdef 577 /* Not Yet .. */ 578 if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0) 579 ivp->iov_op = NULL; /* what should it be ?? */ 580 else 581 ivp->iov_op = NULL; 582 #endif 583 uiop->uio_iovcnt++; 584 ivp++; 585 len -= xfer; 586 siz += xfer; 587 mp = mp->m_next; 588 } 589 if (len > 0 && mp == NULL) { 590 error = EBADRPC; 591 vput(vp); 592 nfsm_reply(0); 593 } 594 uiop->uio_resid = siz; 595 if (error = VOP_WRITE(vp, uiop, ioflags, cred)) { 596 vput(vp); 597 nfsm_reply(0); 598 } 599 off = uiop->uio_offset; 600 } 601 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp); 602 vput(vp); 603 nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 604 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 605 nfsm_srvfillattr; 606 if (nfsd->nd_nqlflag != NQL_NOVAL) { 607 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 608 txdr_hyper(&vap->va_filerev, tl); 609 } 610 nfsm_srvdone; 611 } 612 613 /* 614 * nfs create service 615 * now does a truncate to 0 length via. setattr if it already exists 616 */ 617 nfsrv_create(nfsd, mrep, md, dpos, cred, nam, mrq) 618 struct nfsd *nfsd; 619 struct mbuf *mrep, *md; 620 caddr_t dpos; 621 struct ucred *cred; 622 struct mbuf *nam, **mrq; 623 { 624 register struct nfsv2_fattr *fp; 625 struct vattr va; 626 register struct vattr *vap = &va; 627 register struct nfsv2_sattr *sp; 628 register u_long *tl; 629 struct nameidata nd; 630 register caddr_t cp; 631 register long t1; 632 caddr_t bpos; 633 int error = 0, rdev, cache, len, tsize; 634 char *cp2; 635 struct mbuf *mb, *mb2, *mreq; 636 struct vnode *vp; 637 nfsv2fh_t nfh; 638 fhandle_t *fhp; 639 u_quad_t frev; 640 641 nd.ni_cnd.cn_nameiop = 0; 642 fhp = &nfh.fh_generic; 643 nfsm_srvmtofh(fhp); 644 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 645 nd.ni_cnd.cn_cred = cred; 646 nd.ni_cnd.cn_nameiop = CREATE; 647 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART; 648 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, 649 nfsd->nd_procp)) 650 nfsm_reply(0); 651 VATTR_NULL(vap); 652 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 653 /* 654 * Iff doesn't exist, create it 655 * otherwise just truncate to 0 length 656 * should I set the mode too ?? 657 */ 658 if (nd.ni_vp == NULL) { 659 vap->va_type = IFTOVT(fxdr_unsigned(u_long, sp->sa_mode)); 660 if (vap->va_type == VNON) 661 vap->va_type = VREG; 662 vap->va_mode = nfstov_mode(sp->sa_mode); 663 if (nfsd->nd_nqlflag == NQL_NOVAL) 664 rdev = fxdr_unsigned(long, sp->sa_nfssize); 665 else 666 rdev = fxdr_unsigned(long, sp->sa_nqrdev); 667 if (vap->va_type == VREG || vap->va_type == VSOCK) { 668 vrele(nd.ni_startdir); 669 nqsrv_getl(nd.ni_dvp, NQL_WRITE); 670 if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) 671 nfsm_reply(0); 672 FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); 673 } else if (vap->va_type == VCHR || vap->va_type == VBLK || 674 vap->va_type == VFIFO) { 675 if (vap->va_type == VCHR && rdev == 0xffffffff) 676 vap->va_type = VFIFO; 677 if (vap->va_type == VFIFO) { 678 #ifndef FIFO 679 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 680 vput(nd.ni_dvp); 681 error = ENXIO; 682 goto out; 683 #endif /* FIFO */ 684 } else if (error = suser(cred, (u_short *)0)) { 685 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 686 vput(nd.ni_dvp); 687 goto out; 688 } else 689 vap->va_rdev = (dev_t)rdev; 690 nqsrv_getl(nd.ni_dvp, NQL_WRITE); 691 if (error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) { 692 vrele(nd.ni_startdir); 693 nfsm_reply(0); 694 } 695 nd.ni_cnd.cn_nameiop = LOOKUP; 696 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART); 697 nd.ni_cnd.cn_proc = nfsd->nd_procp; 698 nd.ni_cnd.cn_cred = nfsd->nd_procp->p_ucred; 699 if (error = lookup(&nd)) { 700 free(nd.ni_cnd.cn_pnbuf, M_NAMEI); 701 nfsm_reply(0); 702 } 703 FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); 704 if (nd.ni_cnd.cn_flags & ISSYMLINK) { 705 vrele(nd.ni_dvp); 706 vput(nd.ni_vp); 707 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 708 error = EINVAL; 709 nfsm_reply(0); 710 } 711 } else { 712 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 713 vput(nd.ni_dvp); 714 error = ENXIO; 715 goto out; 716 } 717 vp = nd.ni_vp; 718 } else { 719 vrele(nd.ni_startdir); 720 free(nd.ni_cnd.cn_pnbuf, M_NAMEI); 721 vp = nd.ni_vp; 722 if (nd.ni_dvp == vp) 723 vrele(nd.ni_dvp); 724 else 725 vput(nd.ni_dvp); 726 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 727 if (nfsd->nd_nqlflag == NQL_NOVAL) { 728 tsize = fxdr_unsigned(long, sp->sa_nfssize); 729 if (tsize != -1) 730 vap->va_size = (u_quad_t)tsize; 731 else 732 vap->va_size = -1; 733 } else 734 fxdr_hyper(&sp->sa_nqsize, &vap->va_size); 735 if (vap->va_size != -1) { 736 nqsrv_getl(vp, NQL_WRITE); 737 if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) { 738 vput(vp); 739 nfsm_reply(0); 740 } 741 } 742 } 743 bzero((caddr_t)fhp, sizeof(nfh)); 744 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 745 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 746 vput(vp); 747 nfsm_reply(0); 748 } 749 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp); 750 vput(vp); 751 nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 752 nfsm_srvfhtom(fhp); 753 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 754 nfsm_srvfillattr; 755 return (error); 756 nfsmout: 757 if (nd.ni_cnd.cn_nameiop || nd.ni_cnd.cn_flags) 758 vrele(nd.ni_startdir); 759 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 760 if (nd.ni_dvp == nd.ni_vp) 761 vrele(nd.ni_dvp); 762 else 763 vput(nd.ni_dvp); 764 if (nd.ni_vp) 765 vput(nd.ni_vp); 766 return (error); 767 768 out: 769 vrele(nd.ni_startdir); 770 free(nd.ni_cnd.cn_pnbuf, M_NAMEI); 771 nfsm_reply(0); 772 } 773 774 /* 775 * nfs remove service 776 */ 777 nfsrv_remove(nfsd, mrep, md, dpos, cred, nam, mrq) 778 struct nfsd *nfsd; 779 struct mbuf *mrep, *md; 780 caddr_t dpos; 781 struct ucred *cred; 782 struct mbuf *nam, **mrq; 783 { 784 struct nameidata nd; 785 register u_long *tl; 786 register long t1; 787 caddr_t bpos; 788 int error = 0, cache, len; 789 char *cp2; 790 struct mbuf *mb, *mreq; 791 struct vnode *vp; 792 nfsv2fh_t nfh; 793 fhandle_t *fhp; 794 u_quad_t frev; 795 796 fhp = &nfh.fh_generic; 797 nfsm_srvmtofh(fhp); 798 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 799 nd.ni_cnd.cn_cred = cred; 800 nd.ni_cnd.cn_nameiop = DELETE; 801 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 802 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, 803 nfsd->nd_procp)) 804 nfsm_reply(0); 805 vp = nd.ni_vp; 806 if (vp->v_type == VDIR && 807 (error = suser(cred, (u_short *)0))) 808 goto out; 809 /* 810 * The root of a mounted filesystem cannot be deleted. 811 */ 812 if (vp->v_flag & VROOT) { 813 error = EBUSY; 814 goto out; 815 } 816 if (vp->v_flag & VTEXT) 817 (void) vnode_pager_uncache(vp); 818 out: 819 if (!error) { 820 nqsrv_getl(nd.ni_dvp, NQL_WRITE); 821 nqsrv_getl(vp, NQL_WRITE); 822 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 823 } else { 824 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 825 if (nd.ni_dvp == vp) 826 vrele(nd.ni_dvp); 827 else 828 vput(nd.ni_dvp); 829 vput(vp); 830 } 831 nfsm_reply(0); 832 nfsm_srvdone; 833 } 834 835 /* 836 * nfs rename service 837 */ 838 nfsrv_rename(nfsd, mrep, md, dpos, cred, nam, mrq) 839 struct nfsd *nfsd; 840 struct mbuf *mrep, *md; 841 caddr_t dpos; 842 struct ucred *cred; 843 struct mbuf *nam, **mrq; 844 { 845 register u_long *tl; 846 register long t1; 847 caddr_t bpos; 848 int error = 0, rdonly, cache, len, len2; 849 char *cp2; 850 struct mbuf *mb, *mreq; 851 struct nameidata fromnd, tond; 852 struct vnode *fvp, *tvp, *tdvp; 853 nfsv2fh_t fnfh, tnfh; 854 fhandle_t *ffhp, *tfhp; 855 u_quad_t frev; 856 uid_t saved_uid; 857 858 ffhp = &fnfh.fh_generic; 859 tfhp = &tnfh.fh_generic; 860 fromnd.ni_cnd.cn_nameiop = 0; 861 tond.ni_cnd.cn_nameiop = 0; 862 nfsm_srvmtofh(ffhp); 863 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 864 /* 865 * Remember our original uid so that we can reset cr_uid before 866 * the second nfs_namei() call, in case it is remapped. 867 */ 868 saved_uid = cred->cr_uid; 869 fromnd.ni_cnd.cn_cred = cred; 870 fromnd.ni_cnd.cn_nameiop = DELETE; 871 fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART; 872 if (error = nfs_namei(&fromnd, ffhp, len, nfsd->nd_slp, nam, &md, 873 &dpos, nfsd->nd_procp)) 874 nfsm_reply(0); 875 fvp = fromnd.ni_vp; 876 nfsm_srvmtofh(tfhp); 877 nfsm_strsiz(len2, NFS_MAXNAMLEN); 878 cred->cr_uid = saved_uid; 879 tond.ni_cnd.cn_cred = cred; 880 tond.ni_cnd.cn_nameiop = RENAME; 881 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART; 882 if (error = nfs_namei(&tond, tfhp, len2, nfsd->nd_slp, nam, &md, 883 &dpos, nfsd->nd_procp)) { 884 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 885 vrele(fromnd.ni_dvp); 886 vrele(fvp); 887 goto out1; 888 } 889 tdvp = tond.ni_dvp; 890 tvp = tond.ni_vp; 891 if (tvp != NULL) { 892 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 893 error = EISDIR; 894 goto out; 895 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 896 error = ENOTDIR; 897 goto out; 898 } 899 if (tvp->v_type == VDIR && tvp->v_mountedhere) { 900 error = EXDEV; 901 goto out; 902 } 903 } 904 if (fvp->v_type == VDIR && fvp->v_mountedhere) { 905 error = EBUSY; 906 goto out; 907 } 908 if (fvp->v_mount != tdvp->v_mount) { 909 error = EXDEV; 910 goto out; 911 } 912 if (fvp == tdvp) 913 error = EINVAL; 914 /* 915 * If source is the same as the destination (that is the 916 * same vnode with the same name in the same directory), 917 * then there is nothing to do. 918 */ 919 if (fvp == tvp && fromnd.ni_dvp == tdvp && 920 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 921 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 922 fromnd.ni_cnd.cn_namelen)) 923 error = -1; 924 out: 925 if (!error) { 926 nqsrv_getl(fromnd.ni_dvp, NQL_WRITE); 927 nqsrv_getl(tdvp, NQL_WRITE); 928 if (tvp) 929 nqsrv_getl(tvp, NQL_WRITE); 930 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 931 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 932 } else { 933 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 934 if (tdvp == tvp) 935 vrele(tdvp); 936 else 937 vput(tdvp); 938 if (tvp) 939 vput(tvp); 940 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 941 vrele(fromnd.ni_dvp); 942 vrele(fvp); 943 } 944 vrele(tond.ni_startdir); 945 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 946 out1: 947 vrele(fromnd.ni_startdir); 948 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 949 nfsm_reply(0); 950 return (error); 951 952 nfsmout: 953 if (tond.ni_cnd.cn_nameiop || tond.ni_cnd.cn_flags) { 954 vrele(tond.ni_startdir); 955 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 956 } 957 if (fromnd.ni_cnd.cn_nameiop || fromnd.ni_cnd.cn_flags) { 958 vrele(fromnd.ni_startdir); 959 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 960 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 961 vrele(fromnd.ni_dvp); 962 vrele(fvp); 963 } 964 return (error); 965 } 966 967 /* 968 * nfs link service 969 */ 970 nfsrv_link(nfsd, mrep, md, dpos, cred, nam, mrq) 971 struct nfsd *nfsd; 972 struct mbuf *mrep, *md; 973 caddr_t dpos; 974 struct ucred *cred; 975 struct mbuf *nam, **mrq; 976 { 977 struct nameidata nd; 978 register u_long *tl; 979 register long t1; 980 caddr_t bpos; 981 int error = 0, rdonly, cache, len; 982 char *cp2; 983 struct mbuf *mb, *mreq; 984 struct vnode *vp, *xp; 985 nfsv2fh_t nfh, dnfh; 986 fhandle_t *fhp, *dfhp; 987 u_quad_t frev; 988 989 fhp = &nfh.fh_generic; 990 dfhp = &dnfh.fh_generic; 991 nfsm_srvmtofh(fhp); 992 nfsm_srvmtofh(dfhp); 993 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 994 if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 995 nfsm_reply(0); 996 if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0))) 997 goto out1; 998 nd.ni_cnd.cn_cred = cred; 999 nd.ni_cnd.cn_nameiop = CREATE; 1000 nd.ni_cnd.cn_flags = LOCKPARENT; 1001 if (error = nfs_namei(&nd, dfhp, len, nfsd->nd_slp, nam, &md, &dpos, 1002 nfsd->nd_procp)) 1003 goto out1; 1004 xp = nd.ni_vp; 1005 if (xp != NULL) { 1006 error = EEXIST; 1007 goto out; 1008 } 1009 xp = nd.ni_dvp; 1010 if (vp->v_mount != xp->v_mount) 1011 error = EXDEV; 1012 out: 1013 if (!error) { 1014 nqsrv_getl(vp, NQL_WRITE); 1015 nqsrv_getl(xp, NQL_WRITE); 1016 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1017 } else { 1018 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1019 if (nd.ni_dvp == nd.ni_vp) 1020 vrele(nd.ni_dvp); 1021 else 1022 vput(nd.ni_dvp); 1023 if (nd.ni_vp) 1024 vrele(nd.ni_vp); 1025 } 1026 out1: 1027 vrele(vp); 1028 nfsm_reply(0); 1029 nfsm_srvdone; 1030 } 1031 1032 /* 1033 * nfs symbolic link service 1034 */ 1035 nfsrv_symlink(nfsd, mrep, md, dpos, cred, nam, mrq) 1036 struct nfsd *nfsd; 1037 struct mbuf *mrep, *md; 1038 caddr_t dpos; 1039 struct ucred *cred; 1040 struct mbuf *nam, **mrq; 1041 { 1042 struct vattr va; 1043 struct nameidata nd; 1044 register struct vattr *vap = &va; 1045 register u_long *tl; 1046 register long t1; 1047 struct nfsv2_sattr *sp; 1048 caddr_t bpos; 1049 struct uio io; 1050 struct iovec iv; 1051 int error = 0, rdonly, cache, len, len2; 1052 char *pathcp, *cp2; 1053 struct mbuf *mb, *mreq; 1054 nfsv2fh_t nfh; 1055 fhandle_t *fhp; 1056 u_quad_t frev; 1057 1058 pathcp = (char *)0; 1059 fhp = &nfh.fh_generic; 1060 nfsm_srvmtofh(fhp); 1061 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1062 nd.ni_cnd.cn_cred = cred; 1063 nd.ni_cnd.cn_nameiop = CREATE; 1064 nd.ni_cnd.cn_flags = LOCKPARENT; 1065 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, 1066 nfsd->nd_procp)) 1067 goto out; 1068 nfsm_strsiz(len2, NFS_MAXPATHLEN); 1069 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 1070 iv.iov_base = pathcp; 1071 iv.iov_len = len2; 1072 io.uio_resid = len2; 1073 io.uio_offset = 0; 1074 io.uio_iov = &iv; 1075 io.uio_iovcnt = 1; 1076 io.uio_segflg = UIO_SYSSPACE; 1077 io.uio_rw = UIO_READ; 1078 io.uio_procp = (struct proc *)0; 1079 nfsm_mtouio(&io, len2); 1080 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 1081 *(pathcp + len2) = '\0'; 1082 if (nd.ni_vp) { 1083 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1084 if (nd.ni_dvp == nd.ni_vp) 1085 vrele(nd.ni_dvp); 1086 else 1087 vput(nd.ni_dvp); 1088 vrele(nd.ni_vp); 1089 error = EEXIST; 1090 goto out; 1091 } 1092 VATTR_NULL(vap); 1093 vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode); 1094 nqsrv_getl(nd.ni_dvp, NQL_WRITE); 1095 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp); 1096 out: 1097 if (pathcp) 1098 FREE(pathcp, M_TEMP); 1099 nfsm_reply(0); 1100 return (error); 1101 nfsmout: 1102 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1103 if (nd.ni_dvp == nd.ni_vp) 1104 vrele(nd.ni_dvp); 1105 else 1106 vput(nd.ni_dvp); 1107 if (nd.ni_vp) 1108 vrele(nd.ni_vp); 1109 if (pathcp) 1110 FREE(pathcp, M_TEMP); 1111 return (error); 1112 } 1113 1114 /* 1115 * nfs mkdir service 1116 */ 1117 nfsrv_mkdir(nfsd, mrep, md, dpos, cred, nam, mrq) 1118 struct nfsd *nfsd; 1119 struct mbuf *mrep, *md; 1120 caddr_t dpos; 1121 struct ucred *cred; 1122 struct mbuf *nam, **mrq; 1123 { 1124 struct vattr va; 1125 register struct vattr *vap = &va; 1126 register struct nfsv2_fattr *fp; 1127 struct nameidata nd; 1128 register caddr_t cp; 1129 register u_long *tl; 1130 register long t1; 1131 caddr_t bpos; 1132 int error = 0, rdonly, cache, len; 1133 char *cp2; 1134 struct mbuf *mb, *mb2, *mreq; 1135 struct vnode *vp; 1136 nfsv2fh_t nfh; 1137 fhandle_t *fhp; 1138 u_quad_t frev; 1139 1140 fhp = &nfh.fh_generic; 1141 nfsm_srvmtofh(fhp); 1142 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1143 nd.ni_cnd.cn_cred = cred; 1144 nd.ni_cnd.cn_nameiop = CREATE; 1145 nd.ni_cnd.cn_flags = LOCKPARENT; 1146 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, 1147 nfsd->nd_procp)) 1148 nfsm_reply(0); 1149 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1150 VATTR_NULL(vap); 1151 vap->va_type = VDIR; 1152 vap->va_mode = nfstov_mode(*tl++); 1153 vp = nd.ni_vp; 1154 if (vp != NULL) { 1155 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1156 if (nd.ni_dvp == vp) 1157 vrele(nd.ni_dvp); 1158 else 1159 vput(nd.ni_dvp); 1160 vrele(vp); 1161 error = EEXIST; 1162 nfsm_reply(0); 1163 } 1164 nqsrv_getl(nd.ni_dvp, NQL_WRITE); 1165 if (error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) 1166 nfsm_reply(0); 1167 vp = nd.ni_vp; 1168 bzero((caddr_t)fhp, sizeof(nfh)); 1169 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1170 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 1171 vput(vp); 1172 nfsm_reply(0); 1173 } 1174 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp); 1175 vput(vp); 1176 nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 1177 nfsm_srvfhtom(fhp); 1178 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); 1179 nfsm_srvfillattr; 1180 return (error); 1181 nfsmout: 1182 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1183 if (nd.ni_dvp == nd.ni_vp) 1184 vrele(nd.ni_dvp); 1185 else 1186 vput(nd.ni_dvp); 1187 if (nd.ni_vp) 1188 vrele(nd.ni_vp); 1189 return (error); 1190 } 1191 1192 /* 1193 * nfs rmdir service 1194 */ 1195 nfsrv_rmdir(nfsd, mrep, md, dpos, cred, nam, mrq) 1196 struct nfsd *nfsd; 1197 struct mbuf *mrep, *md; 1198 caddr_t dpos; 1199 struct ucred *cred; 1200 struct mbuf *nam, **mrq; 1201 { 1202 register u_long *tl; 1203 register long t1; 1204 caddr_t bpos; 1205 int error = 0, rdonly, cache, len; 1206 char *cp2; 1207 struct mbuf *mb, *mreq; 1208 struct vnode *vp; 1209 nfsv2fh_t nfh; 1210 fhandle_t *fhp; 1211 struct nameidata nd; 1212 u_quad_t frev; 1213 1214 fhp = &nfh.fh_generic; 1215 nfsm_srvmtofh(fhp); 1216 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1217 nd.ni_cnd.cn_cred = cred; 1218 nd.ni_cnd.cn_nameiop = DELETE; 1219 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 1220 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, 1221 nfsd->nd_procp)) 1222 nfsm_reply(0); 1223 vp = nd.ni_vp; 1224 if (vp->v_type != VDIR) { 1225 error = ENOTDIR; 1226 goto out; 1227 } 1228 /* 1229 * No rmdir "." please. 1230 */ 1231 if (nd.ni_dvp == vp) { 1232 error = EINVAL; 1233 goto out; 1234 } 1235 /* 1236 * The root of a mounted filesystem cannot be deleted. 1237 */ 1238 if (vp->v_flag & VROOT) 1239 error = EBUSY; 1240 out: 1241 if (!error) { 1242 nqsrv_getl(nd.ni_dvp, NQL_WRITE); 1243 nqsrv_getl(vp, NQL_WRITE); 1244 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1245 } else { 1246 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1247 if (nd.ni_dvp == nd.ni_vp) 1248 vrele(nd.ni_dvp); 1249 else 1250 vput(nd.ni_dvp); 1251 vput(vp); 1252 } 1253 nfsm_reply(0); 1254 nfsm_srvdone; 1255 } 1256 1257 /* 1258 * nfs readdir service 1259 * - mallocs what it thinks is enough to read 1260 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 1261 * - calls VOP_READDIR() 1262 * - loops around building the reply 1263 * if the output generated exceeds count break out of loop 1264 * The nfsm_clget macro is used here so that the reply will be packed 1265 * tightly in mbuf clusters. 1266 * - it only knows that it has encountered eof when the VOP_READDIR() 1267 * reads nothing 1268 * - as such one readdir rpc will return eof false although you are there 1269 * and then the next will return eof 1270 * - it trims out records with d_fileno == 0 1271 * this doesn't matter for Unix clients, but they might confuse clients 1272 * for other os'. 1273 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 1274 * than requested, but this may not apply to all filesystems. For 1275 * example, client NFS does not { although it is never remote mounted 1276 * anyhow } 1277 * The alternate call nqnfsrv_readdirlook() does lookups as well. 1278 * PS: The NFS protocol spec. does not clarify what the "count" byte 1279 * argument is a count of.. just name strings and file id's or the 1280 * entire reply rpc or ... 1281 * I tried just file name and id sizes and it confused the Sun client, 1282 * so I am using the full rpc size now. The "paranoia.." comment refers 1283 * to including the status longwords that are not a part of the dir. 1284 * "entry" structures, but are in the rpc. 1285 */ 1286 struct flrep { 1287 u_long fl_cachable; 1288 u_long fl_duration; 1289 u_long fl_frev[2]; 1290 nfsv2fh_t fl_nfh; 1291 u_long fl_fattr[NFSX_NQFATTR / sizeof (u_long)]; 1292 }; 1293 1294 nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq) 1295 struct nfsd *nfsd; 1296 struct mbuf *mrep, *md; 1297 caddr_t dpos; 1298 struct ucred *cred; 1299 struct mbuf *nam, **mrq; 1300 { 1301 register char *bp, *be; 1302 register struct mbuf *mp; 1303 register struct dirent *dp; 1304 register caddr_t cp; 1305 register u_long *tl; 1306 register long t1; 1307 caddr_t bpos; 1308 struct mbuf *mb, *mb2, *mreq, *mp2; 1309 char *cpos, *cend, *cp2, *rbuf; 1310 struct vnode *vp; 1311 nfsv2fh_t nfh; 1312 fhandle_t *fhp; 1313 struct uio io; 1314 struct iovec iv; 1315 struct vattr va; 1316 int len, nlen, rem, xfer, tsiz, i, error = 0; 1317 int siz, cnt, fullsiz, eofflag, rdonly, cache; 1318 u_quad_t frev; 1319 u_long on, off, toff; 1320 1321 fhp = &nfh.fh_generic; 1322 nfsm_srvmtofh(fhp); 1323 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 1324 toff = fxdr_unsigned(u_long, *tl++); 1325 off = (toff & ~(NFS_DIRBLKSIZ-1)); 1326 on = (toff & (NFS_DIRBLKSIZ-1)); 1327 cnt = fxdr_unsigned(int, *tl); 1328 siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1)); 1329 if (cnt > NFS_MAXREADDIR) 1330 siz = NFS_MAXREADDIR; 1331 fullsiz = siz; 1332 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 1333 nfsm_reply(0); 1334 nqsrv_getl(vp, NQL_READ); 1335 if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) { 1336 vput(vp); 1337 nfsm_reply(0); 1338 } 1339 VOP_UNLOCK(vp); 1340 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1341 again: 1342 iv.iov_base = rbuf; 1343 iv.iov_len = fullsiz; 1344 io.uio_iov = &iv; 1345 io.uio_iovcnt = 1; 1346 io.uio_offset = (off_t)off; 1347 io.uio_resid = fullsiz; 1348 io.uio_segflg = UIO_SYSSPACE; 1349 io.uio_rw = UIO_READ; 1350 io.uio_procp = (struct proc *)0; 1351 error = VOP_READDIR(vp, &io, cred); 1352 off = (off_t)io.uio_offset; 1353 if (error) { 1354 vrele(vp); 1355 free((caddr_t)rbuf, M_TEMP); 1356 nfsm_reply(0); 1357 } 1358 if (io.uio_resid < fullsiz) 1359 eofflag = 0; 1360 else 1361 eofflag = 1; 1362 if (io.uio_resid) { 1363 siz -= io.uio_resid; 1364 1365 /* 1366 * If nothing read, return eof 1367 * rpc reply 1368 */ 1369 if (siz == 0) { 1370 vrele(vp); 1371 nfsm_reply(2*NFSX_UNSIGNED); 1372 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 1373 *tl++ = nfs_false; 1374 *tl = nfs_true; 1375 FREE((caddr_t)rbuf, M_TEMP); 1376 return (0); 1377 } 1378 } 1379 1380 /* 1381 * Check for degenerate cases of nothing useful read. 1382 * If so go try again 1383 */ 1384 cpos = rbuf + on; 1385 cend = rbuf + siz; 1386 dp = (struct dirent *)cpos; 1387 while (cpos < cend && dp->d_fileno == 0) { 1388 cpos += dp->d_reclen; 1389 dp = (struct dirent *)cpos; 1390 } 1391 if (cpos >= cend) { 1392 toff = off; 1393 siz = fullsiz; 1394 on = 0; 1395 goto again; 1396 } 1397 1398 cpos = rbuf + on; 1399 cend = rbuf + siz; 1400 dp = (struct dirent *)cpos; 1401 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 1402 nfsm_reply(siz); 1403 mp = mp2 = mb; 1404 bp = bpos; 1405 be = bp + M_TRAILINGSPACE(mp); 1406 1407 /* Loop through the records and build reply */ 1408 while (cpos < cend) { 1409 if (dp->d_fileno != 0) { 1410 nlen = dp->d_namlen; 1411 rem = nfsm_rndup(nlen)-nlen; 1412 len += (4*NFSX_UNSIGNED + nlen + rem); 1413 if (len > cnt) { 1414 eofflag = 0; 1415 break; 1416 } 1417 /* 1418 * Build the directory record xdr from 1419 * the dirent entry. 1420 */ 1421 nfsm_clget; 1422 *tl = nfs_true; 1423 bp += NFSX_UNSIGNED; 1424 nfsm_clget; 1425 *tl = txdr_unsigned(dp->d_fileno); 1426 bp += NFSX_UNSIGNED; 1427 nfsm_clget; 1428 *tl = txdr_unsigned(nlen); 1429 bp += NFSX_UNSIGNED; 1430 1431 /* And loop around copying the name */ 1432 xfer = nlen; 1433 cp = dp->d_name; 1434 while (xfer > 0) { 1435 nfsm_clget; 1436 if ((bp+xfer) > be) 1437 tsiz = be-bp; 1438 else 1439 tsiz = xfer; 1440 bcopy(cp, bp, tsiz); 1441 bp += tsiz; 1442 xfer -= tsiz; 1443 if (xfer > 0) 1444 cp += tsiz; 1445 } 1446 /* And null pad to a long boundary */ 1447 for (i = 0; i < rem; i++) 1448 *bp++ = '\0'; 1449 nfsm_clget; 1450 1451 /* Finish off the record */ 1452 toff += dp->d_reclen; 1453 *tl = txdr_unsigned(toff); 1454 bp += NFSX_UNSIGNED; 1455 } else 1456 toff += dp->d_reclen; 1457 cpos += dp->d_reclen; 1458 dp = (struct dirent *)cpos; 1459 } 1460 vrele(vp); 1461 nfsm_clget; 1462 *tl = nfs_false; 1463 bp += NFSX_UNSIGNED; 1464 nfsm_clget; 1465 if (eofflag) 1466 *tl = nfs_true; 1467 else 1468 *tl = nfs_false; 1469 bp += NFSX_UNSIGNED; 1470 if (mp != mb) { 1471 if (bp < be) 1472 mp->m_len = bp - mtod(mp, caddr_t); 1473 } else 1474 mp->m_len += bp - bpos; 1475 FREE(rbuf, M_TEMP); 1476 nfsm_srvdone; 1477 } 1478 1479 nqnfsrv_readdirlook(nfsd, mrep, md, dpos, cred, nam, mrq) 1480 struct nfsd *nfsd; 1481 struct mbuf *mrep, *md; 1482 caddr_t dpos; 1483 struct ucred *cred; 1484 struct mbuf *nam, **mrq; 1485 { 1486 register char *bp, *be; 1487 register struct mbuf *mp; 1488 register struct dirent *dp; 1489 register caddr_t cp; 1490 register u_long *tl; 1491 register long t1; 1492 caddr_t bpos; 1493 struct mbuf *mb, *mb2, *mreq, *mp2; 1494 char *cpos, *cend, *cp2, *rbuf; 1495 struct vnode *vp, *nvp; 1496 struct flrep fl; 1497 nfsv2fh_t nfh; 1498 fhandle_t *fhp; 1499 struct uio io; 1500 struct iovec iv; 1501 struct vattr va, *vap = &va; 1502 struct nfsv2_fattr *fp; 1503 int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2; 1504 int siz, cnt, fullsiz, eofflag, rdonly, cache; 1505 u_quad_t frev, frev2; 1506 u_long on, off, toff; 1507 1508 fhp = &nfh.fh_generic; 1509 nfsm_srvmtofh(fhp); 1510 nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED); 1511 toff = fxdr_unsigned(u_long, *tl++); 1512 off = (toff & ~(NFS_DIRBLKSIZ-1)); 1513 on = (toff & (NFS_DIRBLKSIZ-1)); 1514 cnt = fxdr_unsigned(int, *tl++); 1515 duration2 = fxdr_unsigned(int, *tl); 1516 siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1)); 1517 if (cnt > NFS_MAXREADDIR) 1518 siz = NFS_MAXREADDIR; 1519 fullsiz = siz; 1520 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 1521 nfsm_reply(0); 1522 nqsrv_getl(vp, NQL_READ); 1523 if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) { 1524 vput(vp); 1525 nfsm_reply(0); 1526 } 1527 VOP_UNLOCK(vp); 1528 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1529 again: 1530 iv.iov_base = rbuf; 1531 iv.iov_len = fullsiz; 1532 io.uio_iov = &iv; 1533 io.uio_iovcnt = 1; 1534 io.uio_offset = (off_t)off; 1535 io.uio_resid = fullsiz; 1536 io.uio_segflg = UIO_SYSSPACE; 1537 io.uio_rw = UIO_READ; 1538 io.uio_procp = (struct proc *)0; 1539 error = VOP_READDIR(vp, &io, cred); 1540 off = (u_long)io.uio_offset; 1541 if (error) { 1542 vrele(vp); 1543 free((caddr_t)rbuf, M_TEMP); 1544 nfsm_reply(0); 1545 } 1546 if (io.uio_resid < fullsiz) 1547 eofflag = 0; 1548 else 1549 eofflag = 1; 1550 if (io.uio_resid) { 1551 siz -= io.uio_resid; 1552 1553 /* 1554 * If nothing read, return eof 1555 * rpc reply 1556 */ 1557 if (siz == 0) { 1558 vrele(vp); 1559 nfsm_reply(2 * NFSX_UNSIGNED); 1560 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1561 *tl++ = nfs_false; 1562 *tl = nfs_true; 1563 FREE((caddr_t)rbuf, M_TEMP); 1564 return (0); 1565 } 1566 } 1567 1568 /* 1569 * Check for degenerate cases of nothing useful read. 1570 * If so go try again 1571 */ 1572 cpos = rbuf + on; 1573 cend = rbuf + siz; 1574 dp = (struct dirent *)cpos; 1575 while (cpos < cend && dp->d_fileno == 0) { 1576 cpos += dp->d_reclen; 1577 dp = (struct dirent *)cpos; 1578 } 1579 if (cpos >= cend) { 1580 toff = off; 1581 siz = fullsiz; 1582 on = 0; 1583 goto again; 1584 } 1585 1586 cpos = rbuf + on; 1587 cend = rbuf + siz; 1588 dp = (struct dirent *)cpos; 1589 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 1590 nfsm_reply(siz); 1591 mp = mp2 = mb; 1592 bp = bpos; 1593 be = bp + M_TRAILINGSPACE(mp); 1594 1595 /* Loop through the records and build reply */ 1596 while (cpos < cend) { 1597 if (dp->d_fileno != 0) { 1598 nlen = dp->d_namlen; 1599 rem = nfsm_rndup(nlen)-nlen; 1600 1601 /* 1602 * For readdir_and_lookup get the vnode using 1603 * the file number. 1604 */ 1605 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp)) 1606 goto invalid; 1607 bzero((caddr_t)&fl.fl_nfh, sizeof (nfsv2fh_t)); 1608 fl.fl_nfh.fh_generic.fh_fsid = 1609 nvp->v_mount->mnt_stat.f_fsid; 1610 if (VFS_VPTOFH(nvp, &fl.fl_nfh.fh_generic.fh_fid)) { 1611 vput(nvp); 1612 goto invalid; 1613 } 1614 if (duration2) { 1615 (void) nqsrv_getlease(nvp, &duration2, NQL_READ, 1616 nfsd, nam, &cache2, &frev2, cred); 1617 fl.fl_duration = txdr_unsigned(duration2); 1618 fl.fl_cachable = txdr_unsigned(cache2); 1619 txdr_hyper(&frev2, fl.fl_frev); 1620 } else 1621 fl.fl_duration = 0; 1622 if (VOP_GETATTR(nvp, vap, cred, nfsd->nd_procp)) { 1623 vput(nvp); 1624 goto invalid; 1625 } 1626 vput(nvp); 1627 fp = (struct nfsv2_fattr *)&fl.fl_fattr; 1628 nfsm_srvfillattr; 1629 len += (4*NFSX_UNSIGNED + nlen + rem + NFSX_FH 1630 + NFSX_NQFATTR); 1631 if (len > cnt) { 1632 eofflag = 0; 1633 break; 1634 } 1635 /* 1636 * Build the directory record xdr from 1637 * the dirent entry. 1638 */ 1639 nfsm_clget; 1640 *tl = nfs_true; 1641 bp += NFSX_UNSIGNED; 1642 1643 /* 1644 * For readdir_and_lookup copy the stuff out. 1645 */ 1646 xfer = sizeof (struct flrep); 1647 cp = (caddr_t)&fl; 1648 while (xfer > 0) { 1649 nfsm_clget; 1650 if ((bp+xfer) > be) 1651 tsiz = be-bp; 1652 else 1653 tsiz = xfer; 1654 bcopy(cp, bp, tsiz); 1655 bp += tsiz; 1656 xfer -= tsiz; 1657 if (xfer > 0) 1658 cp += tsiz; 1659 } 1660 nfsm_clget; 1661 *tl = txdr_unsigned(dp->d_fileno); 1662 bp += NFSX_UNSIGNED; 1663 nfsm_clget; 1664 *tl = txdr_unsigned(nlen); 1665 bp += NFSX_UNSIGNED; 1666 1667 /* And loop around copying the name */ 1668 xfer = nlen; 1669 cp = dp->d_name; 1670 while (xfer > 0) { 1671 nfsm_clget; 1672 if ((bp+xfer) > be) 1673 tsiz = be-bp; 1674 else 1675 tsiz = xfer; 1676 bcopy(cp, bp, tsiz); 1677 bp += tsiz; 1678 xfer -= tsiz; 1679 if (xfer > 0) 1680 cp += tsiz; 1681 } 1682 /* And null pad to a long boundary */ 1683 for (i = 0; i < rem; i++) 1684 *bp++ = '\0'; 1685 nfsm_clget; 1686 1687 /* Finish off the record */ 1688 toff += dp->d_reclen; 1689 *tl = txdr_unsigned(toff); 1690 bp += NFSX_UNSIGNED; 1691 } else 1692 invalid: 1693 toff += dp->d_reclen; 1694 cpos += dp->d_reclen; 1695 dp = (struct dirent *)cpos; 1696 } 1697 vrele(vp); 1698 nfsm_clget; 1699 *tl = nfs_false; 1700 bp += NFSX_UNSIGNED; 1701 nfsm_clget; 1702 if (eofflag) 1703 *tl = nfs_true; 1704 else 1705 *tl = nfs_false; 1706 bp += NFSX_UNSIGNED; 1707 if (mp != mb) { 1708 if (bp < be) 1709 mp->m_len = bp - mtod(mp, caddr_t); 1710 } else 1711 mp->m_len += bp - bpos; 1712 FREE(rbuf, M_TEMP); 1713 nfsm_srvdone; 1714 } 1715 1716 /* 1717 * nfs statfs service 1718 */ 1719 nfsrv_statfs(nfsd, mrep, md, dpos, cred, nam, mrq) 1720 struct nfsd *nfsd; 1721 struct mbuf *mrep, *md; 1722 caddr_t dpos; 1723 struct ucred *cred; 1724 struct mbuf *nam, **mrq; 1725 { 1726 register struct statfs *sf; 1727 register struct nfsv2_statfs *sfp; 1728 register u_long *tl; 1729 register long t1; 1730 caddr_t bpos; 1731 int error = 0, rdonly, cache, isnq; 1732 char *cp2; 1733 struct mbuf *mb, *mb2, *mreq; 1734 struct vnode *vp; 1735 nfsv2fh_t nfh; 1736 fhandle_t *fhp; 1737 struct statfs statfs; 1738 u_quad_t frev; 1739 1740 fhp = &nfh.fh_generic; 1741 isnq = (nfsd->nd_nqlflag != NQL_NOVAL); 1742 nfsm_srvmtofh(fhp); 1743 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) 1744 nfsm_reply(0); 1745 sf = &statfs; 1746 error = VFS_STATFS(vp->v_mount, sf, nfsd->nd_procp); 1747 vput(vp); 1748 nfsm_reply(NFSX_STATFS(isnq)); 1749 nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq)); 1750 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 1751 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 1752 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 1753 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 1754 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 1755 if (isnq) { 1756 sfp->sf_files = txdr_unsigned(sf->f_files); 1757 sfp->sf_ffree = txdr_unsigned(sf->f_ffree); 1758 } 1759 nfsm_srvdone; 1760 } 1761 1762 /* 1763 * Null operation, used by clients to ping server 1764 */ 1765 /* ARGSUSED */ 1766 nfsrv_null(nfsd, mrep, md, dpos, cred, nam, mrq) 1767 struct nfsd *nfsd; 1768 struct mbuf *mrep, *md; 1769 caddr_t dpos; 1770 struct ucred *cred; 1771 struct mbuf *nam, **mrq; 1772 { 1773 caddr_t bpos; 1774 int error = VNOVAL, cache; 1775 struct mbuf *mb, *mreq; 1776 u_quad_t frev; 1777 1778 nfsm_reply(0); 1779 return (error); 1780 } 1781 1782 /* 1783 * No operation, used for obsolete procedures 1784 */ 1785 /* ARGSUSED */ 1786 nfsrv_noop(nfsd, mrep, md, dpos, cred, nam, mrq) 1787 struct nfsd *nfsd; 1788 struct mbuf *mrep, *md; 1789 caddr_t dpos; 1790 struct ucred *cred; 1791 struct mbuf *nam, **mrq; 1792 { 1793 caddr_t bpos; 1794 int error, cache; 1795 struct mbuf *mb, *mreq; 1796 u_quad_t frev; 1797 1798 if (nfsd->nd_repstat) 1799 error = nfsd->nd_repstat; 1800 else 1801 error = EPROCUNAVAIL; 1802 nfsm_reply(0); 1803 return (error); 1804 } 1805 1806 /* 1807 * Perform access checking for vnodes obtained from file handles that would 1808 * refer to files already opened by a Unix client. You cannot just use 1809 * vn_writechk() and VOP_ACCESS() for two reasons. 1810 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 1811 * 2 - The owner is to be given access irrespective of mode bits so that 1812 * processes that chmod after opening a file don't break. I don't like 1813 * this because it opens a security hole, but since the nfs server opens 1814 * a security hole the size of a barn door anyhow, what the heck. 1815 */ 1816 nfsrv_access(vp, flags, cred, rdonly, p) 1817 register struct vnode *vp; 1818 int flags; 1819 register struct ucred *cred; 1820 int rdonly; 1821 struct proc *p; 1822 { 1823 struct vattr vattr; 1824 int error; 1825 if (flags & VWRITE) { 1826 /* Just vn_writechk() changed to check rdonly */ 1827 /* 1828 * Disallow write attempts on read-only file systems; 1829 * unless the file is a socket or a block or character 1830 * device resident on the file system. 1831 */ 1832 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 1833 switch (vp->v_type) { 1834 case VREG: case VDIR: case VLNK: 1835 return (EROFS); 1836 } 1837 } 1838 /* 1839 * If there's shared text associated with 1840 * the inode, try to free it up once. If 1841 * we fail, we can't allow writing. 1842 */ 1843 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 1844 return (ETXTBSY); 1845 } 1846 if (error = VOP_GETATTR(vp, &vattr, cred, p)) 1847 return (error); 1848 if ((error = VOP_ACCESS(vp, flags, cred, p)) && 1849 cred->cr_uid != vattr.va_uid) 1850 return (error); 1851 return (0); 1852 } 1853