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