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