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