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