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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_serv.c 7.40 (Berkeley) 5/15/91 37 * 38 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE 39 * -------------------- ----- ---------------------- 40 * CURRENT PATCH LEVEL: 3 00090 41 * -------------------- ----- ---------------------- 42 * 43 * 08 Sep 92 Rick "gopher I" Fix "truncate" (conflicting?) 44 * 28 Aug 92 Arne Henrik Juul Fixed NFS "create" bug 45 * 02 Mar 92 Greg Hackney Make NFS POSIX compliant (anon fix) 46 */ 47 48 /* 49 * nfs version 2 server calls to vnode ops 50 * - these routines generally have 3 phases 51 * 1 - break down and validate rpc request in mbuf list 52 * 2 - do the vnode ops for the request 53 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c) 54 * 3 - build the rpc reply in an mbuf list 55 * nb: 56 * - do not mix the phases, since the nfsm_?? macros can return failures 57 * on a bad rpc or similar and do not do any vrele() or vput()'s 58 * 59 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs 60 * error number iff error != 0 whereas 61 * returning an error from the server function implies a fatal error 62 * such as a badly constructed rpc request that should be dropped without 63 * a reply. 64 */ 65 66 #include "param.h" 67 #include "proc.h" 68 #include "file.h" 69 #include "namei.h" 70 #include "vnode.h" 71 #include "mount.h" 72 #include "mbuf.h" 73 74 #include "../ufs/quota.h" 75 #include "../ufs/inode.h" 76 #include "../ufs/dir.h" 77 78 #include "nfsv2.h" 79 #include "nfs.h" 80 #include "xdr_subs.h" 81 #include "nfsm_subs.h" 82 83 /* Defs */ 84 #define TRUE 1 85 #define FALSE 0 86 87 /* Global vars */ 88 extern u_long nfs_procids[NFS_NPROCS]; 89 extern u_long nfs_xdrneg1; 90 extern u_long nfs_false, nfs_true; 91 nfstype nfs_type[9]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, 92 NFCHR, NFNON }; 93 94 int nfsrv_null(), 95 nfsrv_getattr(), 96 nfsrv_setattr(), 97 nfsrv_lookup(), 98 nfsrv_readlink(), 99 nfsrv_read(), 100 nfsrv_write(), 101 nfsrv_create(), 102 nfsrv_remove(), 103 nfsrv_rename(), 104 nfsrv_link(), 105 nfsrv_symlink(), 106 nfsrv_mkdir(), 107 nfsrv_rmdir(), 108 nfsrv_readdir(), 109 nfsrv_statfs(), 110 nfsrv_noop(); 111 112 int (*nfsrv_procs[NFS_NPROCS])() = { 113 nfsrv_null, 114 nfsrv_getattr, 115 nfsrv_setattr, 116 nfsrv_noop, 117 nfsrv_lookup, 118 nfsrv_readlink, 119 nfsrv_read, 120 nfsrv_noop, 121 nfsrv_write, 122 nfsrv_create, 123 nfsrv_remove, 124 nfsrv_rename, 125 nfsrv_link, 126 nfsrv_symlink, 127 nfsrv_mkdir, 128 nfsrv_rmdir, 129 nfsrv_readdir, 130 nfsrv_statfs, 131 }; 132 /* 133 * nfs getattr service 134 */ 135 nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat, p) 136 struct mbuf **mrq; 137 struct mbuf *mrep, *md; 138 caddr_t dpos; 139 struct ucred *cred; 140 u_long xid; 141 int *repstat; 142 struct proc *p; 143 { 144 register struct nfsv2_fattr *fp; 145 struct vattr va; 146 register struct vattr *vap = &va; 147 struct vnode *vp; 148 nfsv2fh_t nfh; 149 fhandle_t *fhp; 150 register u_long *tl; 151 register long t1; 152 caddr_t bpos; 153 int error = 0; 154 char *cp2; 155 struct mbuf *mb, *mb2, *mreq; 156 157 fhp = &nfh.fh_generic; 158 nfsm_srvmtofh(fhp); 159 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 160 nfsm_reply(0); 161 error = VOP_GETATTR(vp, vap, cred, p); 162 vput(vp); 163 nfsm_reply(NFSX_FATTR); 164 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 165 nfsm_srvfillattr; 166 nfsm_srvdone; 167 } 168 169 /* 170 * nfs setattr service 171 */ 172 nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat, p) 173 struct mbuf **mrq; 174 struct mbuf *mrep, *md; 175 caddr_t dpos; 176 struct ucred *cred; 177 u_long xid; 178 int *repstat; 179 struct proc *p; 180 { 181 struct vattr va; 182 register struct vattr *vap = &va; 183 register struct nfsv2_sattr *sp; 184 register struct nfsv2_fattr *fp; 185 struct vnode *vp; 186 nfsv2fh_t nfh; 187 fhandle_t *fhp; 188 register u_long *tl; 189 register long t1; 190 caddr_t bpos; 191 int error = 0; 192 char *cp2; 193 struct mbuf *mb, *mb2, *mreq; 194 195 fhp = &nfh.fh_generic; 196 nfsm_srvmtofh(fhp); 197 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); 198 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 199 nfsm_reply(0); 200 if (error = nfsrv_access(vp, VWRITE, cred, p)) 201 goto out; 202 VATTR_NULL(vap); 203 /* 204 * Nah nah nah nah na nah 205 * There is a bug in the Sun client that puts 0xffff in the mode 206 * field of sattr when it should put in 0xffffffff. The u_short 207 * doesn't sign extend. 208 * --> check the low order 2 bytes for 0xffff 209 */ 210 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 211 vap->va_mode = nfstov_mode(sp->sa_mode); 212 if (sp->sa_uid != nfs_xdrneg1) 213 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid); 214 if (sp->sa_gid != nfs_xdrneg1) 215 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid); 216 if (sp->sa_size != nfs_xdrneg1) 217 vap->va_size = fxdr_unsigned(u_long, sp->sa_size); 218 /* 219 * The usec field of sa_atime is overloaded with the va_flags field 220 * for 4.4BSD clients. Hopefully other clients always set both the 221 * sec and usec fields to -1 when not setting the atime. 222 */ 223 if (sp->sa_atime.tv_sec != nfs_xdrneg1) { 224 vap->va_atime.tv_sec = fxdr_unsigned(long, sp->sa_atime.tv_sec); 225 vap->va_atime.tv_usec = 0; 226 } 227 if (sp->sa_atime.tv_usec != nfs_xdrneg1) 228 vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec); 229 if (sp->sa_mtime.tv_sec != nfs_xdrneg1) 230 fxdr_time(&sp->sa_mtime, &vap->va_mtime); 231 if (error = VOP_SETATTR(vp, vap, cred, p)) { 232 vput(vp); 233 nfsm_reply(0); 234 } 235 error = VOP_GETATTR(vp, vap, cred, p); 236 out: 237 vput(vp); 238 nfsm_reply(NFSX_FATTR); 239 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 240 nfsm_srvfillattr; 241 nfsm_srvdone; 242 } 243 244 /* 245 * nfs lookup rpc 246 */ 247 nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat, p) 248 struct mbuf **mrq; 249 struct mbuf *mrep, *md; 250 caddr_t dpos; 251 struct ucred *cred; 252 u_long xid; 253 int *repstat; 254 struct proc *p; 255 { 256 register struct nfsv2_fattr *fp; 257 struct nameidata nd; 258 struct vnode *vp; 259 nfsv2fh_t nfh; 260 fhandle_t *fhp; 261 register caddr_t cp; 262 register u_long *tl; 263 register long t1; 264 caddr_t bpos; 265 int error = 0; 266 char *cp2; 267 struct mbuf *mb, *mb2, *mreq; 268 long len; 269 struct vattr va, *vap = &va; 270 271 fhp = &nfh.fh_generic; 272 nfsm_srvmtofh(fhp); 273 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 274 nd.ni_cred = cred; 275 nd.ni_nameiop = LOOKUP | LOCKLEAF; 276 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 277 nfsm_reply(0); 278 vp = nd.ni_vp; 279 bzero((caddr_t)fhp, sizeof(nfh)); 280 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 281 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 282 vput(vp); 283 nfsm_reply(0); 284 } 285 error = VOP_GETATTR(vp, vap, cred, p); 286 vput(vp); 287 nfsm_reply(NFSX_FH+NFSX_FATTR); 288 nfsm_srvfhtom(fhp); 289 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 290 nfsm_srvfillattr; 291 nfsm_srvdone; 292 } 293 294 /* 295 * nfs readlink service 296 */ 297 nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat, p) 298 struct mbuf **mrq; 299 struct mbuf *mrep, *md; 300 caddr_t dpos; 301 struct ucred *cred; 302 u_long xid; 303 int *repstat; 304 struct proc *p; 305 { 306 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 307 register struct iovec *ivp = iv; 308 register struct mbuf *mp; 309 register u_long *tl; 310 register long t1; 311 caddr_t bpos; 312 int error = 0; 313 char *cp2; 314 struct mbuf *mb, *mb2, *mp2, *mp3, *mreq; 315 struct vnode *vp; 316 nfsv2fh_t nfh; 317 fhandle_t *fhp; 318 struct uio io, *uiop = &io; 319 int i, tlen, len; 320 321 fhp = &nfh.fh_generic; 322 nfsm_srvmtofh(fhp); 323 len = 0; 324 i = 0; 325 while (len < NFS_MAXPATHLEN) { 326 MGET(mp, M_WAIT, MT_DATA); 327 MCLGET(mp, M_WAIT); 328 mp->m_len = NFSMSIZ(mp); 329 if (len == 0) 330 mp3 = mp2 = mp; 331 else { 332 mp2->m_next = mp; 333 mp2 = mp; 334 } 335 if ((len+mp->m_len) > NFS_MAXPATHLEN) { 336 mp->m_len = NFS_MAXPATHLEN-len; 337 len = NFS_MAXPATHLEN; 338 } else 339 len += mp->m_len; 340 ivp->iov_base = mtod(mp, caddr_t); 341 ivp->iov_len = mp->m_len; 342 i++; 343 ivp++; 344 } 345 uiop->uio_iov = iv; 346 uiop->uio_iovcnt = i; 347 uiop->uio_offset = 0; 348 uiop->uio_resid = len; 349 uiop->uio_rw = UIO_READ; 350 uiop->uio_segflg = UIO_SYSSPACE; 351 uiop->uio_procp = (struct proc *)0; 352 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) { 353 m_freem(mp3); 354 nfsm_reply(0); 355 } 356 if (vp->v_type != VLNK) { 357 error = EINVAL; 358 goto out; 359 } 360 error = VOP_READLINK(vp, uiop, cred); 361 out: 362 vput(vp); 363 if (error) 364 m_freem(mp3); 365 nfsm_reply(NFSX_UNSIGNED); 366 if (uiop->uio_resid > 0) { 367 len -= uiop->uio_resid; 368 tlen = nfsm_rndup(len); 369 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len); 370 } 371 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 372 *tl = txdr_unsigned(len); 373 mb->m_next = mp3; 374 nfsm_srvdone; 375 } 376 377 /* 378 * nfs read service 379 */ 380 nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat, p) 381 struct mbuf **mrq; 382 struct mbuf *mrep, *md; 383 caddr_t dpos; 384 struct ucred *cred; 385 u_long xid; 386 int *repstat; 387 struct proc *p; 388 { 389 register struct iovec *iv; 390 struct iovec *iv2; 391 register struct mbuf *m; 392 register struct nfsv2_fattr *fp; 393 register u_long *tl; 394 register long t1; 395 caddr_t bpos; 396 int error = 0; 397 char *cp2; 398 struct mbuf *mb, *mb2, *mreq; 399 struct mbuf *m2, *m3; 400 struct vnode *vp; 401 nfsv2fh_t nfh; 402 fhandle_t *fhp; 403 struct uio io, *uiop = &io; 404 struct vattr va, *vap = &va; 405 int i, cnt, len, left, siz, tlen; 406 off_t off; 407 408 fhp = &nfh.fh_generic; 409 nfsm_srvmtofh(fhp); 410 nfsm_disect(tl, u_long *, NFSX_UNSIGNED); 411 off = fxdr_unsigned(off_t, *tl); 412 nfsm_srvstrsiz(cnt, NFS_MAXDATA); 413 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 414 nfsm_reply(0); 415 if ((error = nfsrv_access(vp, VREAD, cred, p)) && 416 (error = nfsrv_access(vp, VEXEC, cred, p))) { 417 vput(vp); 418 nfsm_reply(0); 419 } 420 len = left = cnt; 421 /* 422 * Generate the mbuf list with the uio_iov ref. to it. 423 */ 424 i = 0; 425 m3 = (struct mbuf *)0; 426 #ifdef lint 427 m2 = (struct mbuf *)0; 428 #endif /* lint */ 429 MALLOC(iv, struct iovec *, 430 ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec), M_TEMP, 431 M_WAITOK); 432 iv2 = iv; 433 while (left > 0) { 434 MGET(m, M_WAIT, MT_DATA); 435 if (left > MINCLSIZE) 436 MCLGET(m, M_WAIT); 437 m->m_len = 0; 438 siz = min(M_TRAILINGSPACE(m), left); 439 m->m_len = siz; 440 iv->iov_base = mtod(m, caddr_t); 441 iv->iov_len = siz; 442 iv++; 443 i++; 444 left -= siz; 445 if (m3) { 446 m2->m_next = m; 447 m2 = m; 448 } else 449 m3 = m2 = m; 450 } 451 uiop->uio_iov = iv2; 452 uiop->uio_iovcnt = i; 453 uiop->uio_offset = off; 454 uiop->uio_resid = cnt; 455 uiop->uio_rw = UIO_READ; 456 uiop->uio_segflg = UIO_SYSSPACE; 457 uiop->uio_procp = (struct proc *)0; 458 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred); 459 off = uiop->uio_offset; 460 FREE((caddr_t)iv2, M_TEMP); 461 if (error) { 462 m_freem(m3); 463 vput(vp); 464 nfsm_reply(0); 465 } 466 if (error = VOP_GETATTR(vp, vap, cred, p)) 467 m_freem(m3); 468 vput(vp); 469 nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED); 470 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 471 nfsm_srvfillattr; 472 len -= uiop->uio_resid; 473 if (len > 0) { 474 tlen = nfsm_rndup(len); 475 if (cnt != tlen || tlen != len) 476 nfsm_adj(m3, cnt-tlen, tlen-len); 477 } else { 478 m_freem(m3); 479 m3 = (struct mbuf *)0; 480 } 481 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 482 *tl = txdr_unsigned(len); 483 mb->m_next = m3; 484 nfsm_srvdone; 485 } 486 487 /* 488 * nfs write service 489 */ 490 nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat, p) 491 struct mbuf *mrep, *md, **mrq; 492 caddr_t dpos; 493 struct ucred *cred; 494 u_long xid; 495 int *repstat; 496 struct proc *p; 497 { 498 register struct iovec *ivp; 499 register struct mbuf *mp; 500 register struct nfsv2_fattr *fp; 501 struct iovec iv[NFS_MAXIOVEC]; 502 struct vattr va; 503 register struct vattr *vap = &va; 504 register u_long *tl; 505 register long t1; 506 caddr_t bpos; 507 int error = 0; 508 char *cp2; 509 struct mbuf *mb, *mb2, *mreq; 510 struct vnode *vp; 511 nfsv2fh_t nfh; 512 fhandle_t *fhp; 513 struct uio io, *uiop = &io; 514 off_t off; 515 long siz, len, xfer; 516 517 fhp = &nfh.fh_generic; 518 nfsm_srvmtofh(fhp); 519 nfsm_disect(tl, u_long *, 4*NFSX_UNSIGNED); 520 off = fxdr_unsigned(off_t, *++tl); 521 tl += 2; 522 len = fxdr_unsigned(long, *tl); 523 if (len > NFS_MAXDATA || len <= 0) { 524 error = EBADRPC; 525 nfsm_reply(0); 526 } 527 if (dpos == (mtod(md, caddr_t)+md->m_len)) { 528 mp = md->m_next; 529 if (mp == NULL) { 530 error = EBADRPC; 531 nfsm_reply(0); 532 } 533 } else { 534 mp = md; 535 siz = dpos-mtod(mp, caddr_t); 536 mp->m_len -= siz; 537 NFSMADV(mp, siz); 538 } 539 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 540 nfsm_reply(0); 541 if (error = nfsrv_access(vp, VWRITE, cred, p)) { 542 vput(vp); 543 nfsm_reply(0); 544 } 545 uiop->uio_resid = 0; 546 uiop->uio_rw = UIO_WRITE; 547 uiop->uio_segflg = UIO_SYSSPACE; 548 uiop->uio_procp = (struct proc *)0; 549 /* 550 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the 551 * loop until done. 552 */ 553 while (len > 0 && uiop->uio_resid == 0) { 554 ivp = iv; 555 siz = 0; 556 uiop->uio_iov = ivp; 557 uiop->uio_iovcnt = 0; 558 uiop->uio_offset = off; 559 while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) { 560 ivp->iov_base = mtod(mp, caddr_t); 561 if (len < mp->m_len) 562 ivp->iov_len = xfer = len; 563 else 564 ivp->iov_len = xfer = mp->m_len; 565 #ifdef notdef 566 /* Not Yet .. */ 567 if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0) 568 ivp->iov_op = NULL; /* what should it be ?? */ 569 else 570 ivp->iov_op = NULL; 571 #endif 572 uiop->uio_iovcnt++; 573 ivp++; 574 len -= xfer; 575 siz += xfer; 576 mp = mp->m_next; 577 } 578 if (len > 0 && mp == NULL) { 579 error = EBADRPC; 580 vput(vp); 581 nfsm_reply(0); 582 } 583 uiop->uio_resid = siz; 584 if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED, 585 cred)) { 586 vput(vp); 587 nfsm_reply(0); 588 } 589 off = uiop->uio_offset; 590 } 591 error = VOP_GETATTR(vp, vap, cred, p); 592 vput(vp); 593 nfsm_reply(NFSX_FATTR); 594 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 595 nfsm_srvfillattr; 596 nfsm_srvdone; 597 } 598 599 /* 600 * nfs create service 601 * if it already exists, just set length * 28 Aug 92* 602 * do NOT truncate unconditionally ! 603 */ 604 nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat, p) 605 struct mbuf *mrep, *md, **mrq; 606 caddr_t dpos; 607 struct ucred *cred; 608 u_long xid; 609 int *repstat; 610 struct proc *p; 611 { 612 register struct nfsv2_fattr *fp; 613 struct vattr va; 614 register struct vattr *vap = &va; 615 struct nameidata nd; 616 register caddr_t cp; 617 register u_long *tl; 618 register long t1; 619 caddr_t bpos; 620 long rdev; 621 int error = 0; 622 char *cp2; 623 struct mbuf *mb, *mb2, *mreq; 624 struct vnode *vp; 625 nfsv2fh_t nfh; 626 fhandle_t *fhp; 627 long len; 628 629 nd.ni_nameiop = 0; 630 fhp = &nfh.fh_generic; 631 nfsm_srvmtofh(fhp); 632 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 633 nd.ni_cred = cred; 634 nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART; 635 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 636 nfsm_reply(0); 637 VATTR_NULL(vap); 638 nfsm_disect(tl, u_long *, NFSX_SATTR); 639 /* 640 * If it doesn't exist, create it * 28 Aug 92* 641 * otherwise just set length from attributes 642 * should I set the mode too ?? 643 */ 644 if (nd.ni_vp == NULL) { 645 vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl)); 646 if (vap->va_type == VNON) 647 vap->va_type = VREG; 648 vap->va_mode = nfstov_mode(*tl); 649 rdev = fxdr_unsigned(long, *(tl+3)); 650 if (vap->va_type == VREG || vap->va_type == VSOCK) { 651 vrele(nd.ni_startdir); 652 if (error = VOP_CREATE(&nd, vap, p)) 653 nfsm_reply(0); 654 FREE(nd.ni_pnbuf, M_NAMEI); 655 } else if (vap->va_type == VCHR || vap->va_type == VBLK || 656 vap->va_type == VFIFO) { 657 if (vap->va_type == VCHR && rdev == 0xffffffff) 658 vap->va_type = VFIFO; 659 if (vap->va_type == VFIFO) { 660 #ifndef FIFO 661 VOP_ABORTOP(&nd); 662 vput(nd.ni_dvp); 663 error = ENXIO; 664 goto out; 665 #endif /* FIFO */ 666 } else if (error = suser(cred, (short *)0)) { 667 VOP_ABORTOP(&nd); 668 vput(nd.ni_dvp); 669 goto out; 670 } else 671 vap->va_rdev = (dev_t)rdev; 672 if (error = VOP_MKNOD(&nd, vap, cred, p)) { 673 vrele(nd.ni_startdir); 674 nfsm_reply(0); 675 } 676 nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART); 677 nd.ni_nameiop |= LOOKUP; 678 if (error = lookup(&nd, p)) { 679 free(nd.ni_pnbuf, M_NAMEI); 680 nfsm_reply(0); 681 } 682 FREE(nd.ni_pnbuf, M_NAMEI); 683 if (nd.ni_more) { 684 vrele(nd.ni_dvp); 685 vput(nd.ni_vp); 686 VOP_ABORTOP(&nd); 687 error = EINVAL; 688 nfsm_reply(0); 689 } 690 } else { 691 VOP_ABORTOP(&nd); 692 vput(nd.ni_dvp); 693 error = ENXIO; 694 goto out; 695 } 696 vp = nd.ni_vp; 697 } else { 698 vrele(nd.ni_startdir); 699 free(nd.ni_pnbuf, M_NAMEI); 700 vp = nd.ni_vp; 701 if (nd.ni_dvp == vp) 702 vrele(nd.ni_dvp); 703 else 704 vput(nd.ni_dvp); 705 VOP_ABORTOP(&nd); 706 vap->va_size = fxdr_unsigned(long, *(tl+3)); /* 28 Aug 92*/ 707 /* 08 Sep 92*/ if (vap->va_size != -1 && (error = VOP_SETATTR(vp, vap, cred, p))) { 708 vput(vp); 709 nfsm_reply(0); 710 } 711 } 712 bzero((caddr_t)fhp, sizeof(nfh)); 713 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 714 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 715 vput(vp); 716 nfsm_reply(0); 717 } 718 error = VOP_GETATTR(vp, vap, cred, p); 719 vput(vp); 720 nfsm_reply(NFSX_FH+NFSX_FATTR); 721 nfsm_srvfhtom(fhp); 722 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 723 nfsm_srvfillattr; 724 return (error); 725 nfsmout: 726 if (nd.ni_nameiop) 727 vrele(nd.ni_startdir); 728 VOP_ABORTOP(&nd); 729 if (nd.ni_dvp == nd.ni_vp) 730 vrele(nd.ni_dvp); 731 else 732 vput(nd.ni_dvp); 733 if (nd.ni_vp) 734 vput(nd.ni_vp); 735 return (error); 736 737 out: 738 vrele(nd.ni_startdir); 739 free(nd.ni_pnbuf, M_NAMEI); 740 nfsm_reply(0); 741 } 742 743 /* 744 * nfs remove service 745 */ 746 nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat, p) 747 struct mbuf *mrep, *md, **mrq; 748 caddr_t dpos; 749 struct ucred *cred; 750 u_long xid; 751 int *repstat; 752 struct proc *p; 753 { 754 struct nameidata nd; 755 register u_long *tl; 756 register long t1; 757 caddr_t bpos; 758 int error = 0; 759 char *cp2; 760 struct mbuf *mb, *mreq; 761 struct vnode *vp; 762 nfsv2fh_t nfh; 763 fhandle_t *fhp; 764 long len; 765 766 fhp = &nfh.fh_generic; 767 nfsm_srvmtofh(fhp); 768 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 769 nd.ni_cred = cred; 770 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 771 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 772 nfsm_reply(0); 773 vp = nd.ni_vp; 774 if (vp->v_type == VDIR && 775 (error = suser(cred, (short *)0))) 776 goto out; 777 /* 778 * The root of a mounted filesystem cannot be deleted. 779 */ 780 if (vp->v_flag & VROOT) { 781 error = EBUSY; 782 goto out; 783 } 784 if (vp->v_flag & VTEXT) 785 (void) vnode_pager_uncache(vp); 786 out: 787 if (!error) { 788 error = VOP_REMOVE(&nd, p); 789 } else { 790 VOP_ABORTOP(&nd); 791 if (nd.ni_dvp == vp) 792 vrele(nd.ni_dvp); 793 else 794 vput(nd.ni_dvp); 795 vput(vp); 796 } 797 nfsm_reply(0); 798 nfsm_srvdone; 799 } 800 801 /* 802 * nfs rename service 803 */ 804 nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat, p) 805 struct mbuf *mrep, *md, **mrq; 806 caddr_t dpos; 807 struct ucred *cred; 808 u_long xid; 809 int *repstat; 810 struct proc *p; 811 { 812 register u_long *tl; 813 register long t1; 814 caddr_t bpos; 815 int error = 0; 816 char *cp2; 817 struct mbuf *mb, *mreq; 818 struct nameidata fromnd, tond; 819 struct vnode *fvp, *tvp, *tdvp; 820 nfsv2fh_t fnfh, tnfh; 821 fhandle_t *ffhp, *tfhp; 822 long len, len2; 823 int rootflg = 0; 824 825 ffhp = &fnfh.fh_generic; 826 tfhp = &tnfh.fh_generic; 827 fromnd.ni_nameiop = 0; 828 tond.ni_nameiop = 0; 829 nfsm_srvmtofh(ffhp); 830 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 831 /* 832 * Remember if we are root so that we can reset cr_uid before 833 * the second nfs_namei() call 834 */ 835 if (cred->cr_uid == 0) 836 rootflg++; 837 fromnd.ni_cred = cred; 838 fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART; 839 if (error = nfs_namei(&fromnd, ffhp, len, &md, &dpos, p)) 840 nfsm_reply(0); 841 fvp = fromnd.ni_vp; 842 nfsm_srvmtofh(tfhp); 843 nfsm_strsiz(len2, NFS_MAXNAMLEN); 844 if (rootflg) 845 cred->cr_uid = 0; 846 tond.ni_cred = cred; 847 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE 848 | SAVESTART; 849 if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos, p)) { 850 VOP_ABORTOP(&fromnd); 851 vrele(fromnd.ni_dvp); 852 vrele(fvp); 853 goto out1; 854 } 855 tdvp = tond.ni_dvp; 856 tvp = tond.ni_vp; 857 if (tvp != NULL) { 858 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 859 error = EISDIR; 860 goto out; 861 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 862 error = ENOTDIR; 863 goto out; 864 } 865 } 866 if (fvp->v_mount != tdvp->v_mount) { 867 error = EXDEV; 868 goto out; 869 } 870 if (fvp == tdvp) 871 error = EINVAL; 872 /* 873 * If source is the same as the destination (that is the 874 * same vnode with the same name in the same directory), 875 * then there is nothing to do. 876 */ 877 if (fvp == tvp && fromnd.ni_dvp == tdvp && 878 fromnd.ni_namelen == tond.ni_namelen && 879 !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen)) 880 error = -1; 881 out: 882 if (!error) { 883 error = VOP_RENAME(&fromnd, &tond, p); 884 } else { 885 VOP_ABORTOP(&tond); 886 if (tdvp == tvp) 887 vrele(tdvp); 888 else 889 vput(tdvp); 890 if (tvp) 891 vput(tvp); 892 VOP_ABORTOP(&fromnd); 893 vrele(fromnd.ni_dvp); 894 vrele(fvp); 895 } 896 vrele(tond.ni_startdir); 897 FREE(tond.ni_pnbuf, M_NAMEI); 898 out1: 899 vrele(fromnd.ni_startdir); 900 FREE(fromnd.ni_pnbuf, M_NAMEI); 901 nfsm_reply(0); 902 return (error); 903 904 nfsmout: 905 if (tond.ni_nameiop) { 906 vrele(tond.ni_startdir); 907 FREE(tond.ni_pnbuf, M_NAMEI); 908 } 909 if (fromnd.ni_nameiop) { 910 vrele(fromnd.ni_startdir); 911 FREE(fromnd.ni_pnbuf, M_NAMEI); 912 VOP_ABORTOP(&fromnd); 913 vrele(fromnd.ni_dvp); 914 vrele(fvp); 915 } 916 return (error); 917 } 918 919 /* 920 * nfs link service 921 */ 922 nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat, p) 923 struct mbuf *mrep, *md, **mrq; 924 caddr_t dpos; 925 struct ucred *cred; 926 u_long xid; 927 int *repstat; 928 struct proc *p; 929 { 930 struct nameidata nd; 931 register u_long *tl; 932 register long t1; 933 caddr_t bpos; 934 int error = 0; 935 char *cp2; 936 struct mbuf *mb, *mreq; 937 struct vnode *vp, *xp; 938 nfsv2fh_t nfh, dnfh; 939 fhandle_t *fhp, *dfhp; 940 long len; 941 942 fhp = &nfh.fh_generic; 943 dfhp = &dnfh.fh_generic; 944 nfsm_srvmtofh(fhp); 945 nfsm_srvmtofh(dfhp); 946 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 947 if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred)) 948 nfsm_reply(0); 949 if (vp->v_type == VDIR && (error = suser(cred, NULL))) 950 goto out1; 951 nd.ni_cred = cred; 952 nd.ni_nameiop = CREATE | LOCKPARENT; 953 if (error = nfs_namei(&nd, dfhp, len, &md, &dpos, p)) 954 goto out1; 955 xp = nd.ni_vp; 956 if (xp != NULL) { 957 error = EEXIST; 958 goto out; 959 } 960 xp = nd.ni_dvp; 961 if (vp->v_mount != xp->v_mount) 962 error = EXDEV; 963 out: 964 if (!error) { 965 error = VOP_LINK(vp, &nd, p); 966 } else { 967 VOP_ABORTOP(&nd); 968 if (nd.ni_dvp == nd.ni_vp) 969 vrele(nd.ni_dvp); 970 else 971 vput(nd.ni_dvp); 972 if (nd.ni_vp) 973 vrele(nd.ni_vp); 974 } 975 out1: 976 vrele(vp); 977 nfsm_reply(0); 978 nfsm_srvdone; 979 } 980 981 /* 982 * nfs symbolic link service 983 */ 984 nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat, p) 985 struct mbuf *mrep, *md, **mrq; 986 caddr_t dpos; 987 struct ucred *cred; 988 u_long xid; 989 int *repstat; 990 struct proc *p; 991 { 992 struct vattr va; 993 struct nameidata nd; 994 register struct vattr *vap = &va; 995 register u_long *tl; 996 register long t1; 997 struct nfsv2_sattr *sp; 998 caddr_t bpos; 999 struct uio io; 1000 struct iovec iv; 1001 int error = 0; 1002 char *pathcp, *cp2; 1003 struct mbuf *mb, *mreq; 1004 nfsv2fh_t nfh; 1005 fhandle_t *fhp; 1006 long len, len2; 1007 1008 pathcp = (char *)0; 1009 fhp = &nfh.fh_generic; 1010 nfsm_srvmtofh(fhp); 1011 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1012 nd.ni_cred = cred; 1013 nd.ni_nameiop = CREATE | LOCKPARENT; 1014 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 1015 goto out; 1016 nfsm_strsiz(len2, NFS_MAXPATHLEN); 1017 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 1018 iv.iov_base = pathcp; 1019 iv.iov_len = len2; 1020 io.uio_resid = len2; 1021 io.uio_offset = 0; 1022 io.uio_iov = &iv; 1023 io.uio_iovcnt = 1; 1024 io.uio_segflg = UIO_SYSSPACE; 1025 io.uio_rw = UIO_READ; 1026 io.uio_procp = (struct proc *)0; 1027 nfsm_mtouio(&io, len2); 1028 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); 1029 *(pathcp + len2) = '\0'; 1030 if (nd.ni_vp) { 1031 VOP_ABORTOP(&nd); 1032 if (nd.ni_dvp == nd.ni_vp) 1033 vrele(nd.ni_dvp); 1034 else 1035 vput(nd.ni_dvp); 1036 vrele(nd.ni_vp); 1037 error = EEXIST; 1038 goto out; 1039 } 1040 VATTR_NULL(vap); 1041 vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode); 1042 error = VOP_SYMLINK(&nd, vap, pathcp, p); 1043 out: 1044 if (pathcp) 1045 FREE(pathcp, M_TEMP); 1046 nfsm_reply(0); 1047 return (error); 1048 nfsmout: 1049 VOP_ABORTOP(&nd); 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 if (pathcp) 1057 FREE(pathcp, M_TEMP); 1058 return (error); 1059 } 1060 1061 /* 1062 * nfs mkdir service 1063 */ 1064 nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat, p) 1065 struct mbuf *mrep, *md, **mrq; 1066 caddr_t dpos; 1067 struct ucred *cred; 1068 u_long xid; 1069 int *repstat; 1070 struct proc *p; 1071 { 1072 struct vattr va; 1073 register struct vattr *vap = &va; 1074 register struct nfsv2_fattr *fp; 1075 struct nameidata nd; 1076 register caddr_t cp; 1077 register u_long *tl; 1078 register long t1; 1079 caddr_t bpos; 1080 int error = 0; 1081 char *cp2; 1082 struct mbuf *mb, *mb2, *mreq; 1083 struct vnode *vp; 1084 nfsv2fh_t nfh; 1085 fhandle_t *fhp; 1086 long len; 1087 1088 fhp = &nfh.fh_generic; 1089 nfsm_srvmtofh(fhp); 1090 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1091 nd.ni_cred = cred; 1092 nd.ni_nameiop = CREATE | LOCKPARENT; 1093 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 1094 nfsm_reply(0); 1095 nfsm_disect(tl, u_long *, NFSX_UNSIGNED); 1096 VATTR_NULL(vap); 1097 vap->va_type = VDIR; 1098 vap->va_mode = nfstov_mode(*tl++); 1099 vp = nd.ni_vp; 1100 if (vp != NULL) { 1101 VOP_ABORTOP(&nd); 1102 if (nd.ni_dvp == vp) 1103 vrele(nd.ni_dvp); 1104 else 1105 vput(nd.ni_dvp); 1106 vrele(vp); 1107 error = EEXIST; 1108 nfsm_reply(0); 1109 } 1110 if (error = VOP_MKDIR(&nd, vap, p)) 1111 nfsm_reply(0); 1112 vp = nd.ni_vp; 1113 bzero((caddr_t)fhp, sizeof(nfh)); 1114 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1115 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 1116 vput(vp); 1117 nfsm_reply(0); 1118 } 1119 error = VOP_GETATTR(vp, vap, cred, p); 1120 vput(vp); 1121 nfsm_reply(NFSX_FH+NFSX_FATTR); 1122 nfsm_srvfhtom(fhp); 1123 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 1124 nfsm_srvfillattr; 1125 return (error); 1126 nfsmout: 1127 VOP_ABORTOP(&nd); 1128 if (nd.ni_dvp == nd.ni_vp) 1129 vrele(nd.ni_dvp); 1130 else 1131 vput(nd.ni_dvp); 1132 if (nd.ni_vp) 1133 vrele(nd.ni_vp); 1134 return (error); 1135 } 1136 1137 /* 1138 * nfs rmdir service 1139 */ 1140 nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat, p) 1141 struct mbuf *mrep, *md, **mrq; 1142 caddr_t dpos; 1143 struct ucred *cred; 1144 u_long xid; 1145 int *repstat; 1146 struct proc *p; 1147 { 1148 register u_long *tl; 1149 register long t1; 1150 caddr_t bpos; 1151 int error = 0; 1152 char *cp2; 1153 struct mbuf *mb, *mreq; 1154 struct vnode *vp; 1155 nfsv2fh_t nfh; 1156 fhandle_t *fhp; 1157 long len; 1158 struct nameidata nd; 1159 1160 fhp = &nfh.fh_generic; 1161 nfsm_srvmtofh(fhp); 1162 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1163 nd.ni_cred = cred; 1164 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 1165 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 1166 nfsm_reply(0); 1167 vp = nd.ni_vp; 1168 if (vp->v_type != VDIR) { 1169 error = ENOTDIR; 1170 goto out; 1171 } 1172 /* 1173 * No rmdir "." please. 1174 */ 1175 if (nd.ni_dvp == vp) { 1176 error = EINVAL; 1177 goto out; 1178 } 1179 /* 1180 * The root of a mounted filesystem cannot be deleted. 1181 */ 1182 if (vp->v_flag & VROOT) 1183 error = EBUSY; 1184 out: 1185 if (!error) { 1186 error = VOP_RMDIR(&nd, p); 1187 } else { 1188 VOP_ABORTOP(&nd); 1189 if (nd.ni_dvp == nd.ni_vp) 1190 vrele(nd.ni_dvp); 1191 else 1192 vput(nd.ni_dvp); 1193 vput(vp); 1194 } 1195 nfsm_reply(0); 1196 nfsm_srvdone; 1197 } 1198 1199 /* 1200 * nfs readdir service 1201 * - mallocs what it thinks is enough to read 1202 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 1203 * - calls VOP_READDIR() 1204 * - loops around building the reply 1205 * if the output generated exceeds count break out of loop 1206 * The nfsm_clget macro is used here so that the reply will be packed 1207 * tightly in mbuf clusters. 1208 * - it only knows that it has encountered eof when the VOP_READDIR() 1209 * reads nothing 1210 * - as such one readdir rpc will return eof false although you are there 1211 * and then the next will return eof 1212 * - it trims out records with d_ino == 0 1213 * this doesn't matter for Unix clients, but they might confuse clients 1214 * for other os'. 1215 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 1216 * than requested, but this may not apply to all filesystems. For 1217 * example, client NFS does not { although it is never remote mounted 1218 * anyhow } 1219 * PS: The NFS protocol spec. does not clarify what the "count" byte 1220 * argument is a count of.. just name strings and file id's or the 1221 * entire reply rpc or ... 1222 * I tried just file name and id sizes and it confused the Sun client, 1223 * so I am using the full rpc size now. The "paranoia.." comment refers 1224 * to including the status longwords that are not a part of the dir. 1225 * "entry" structures, but are in the rpc. 1226 */ 1227 nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat, p) 1228 struct mbuf **mrq; 1229 struct mbuf *mrep, *md; 1230 caddr_t dpos; 1231 struct ucred *cred; 1232 u_long xid; 1233 int *repstat; 1234 struct proc *p; 1235 { 1236 register char *bp, *be; 1237 register struct mbuf *mp; 1238 register struct direct *dp; 1239 register caddr_t cp; 1240 register u_long *tl; 1241 register long t1; 1242 caddr_t bpos; 1243 int error = 0; 1244 char *cp2; 1245 struct mbuf *mb, *mb2, *mreq; 1246 char *cpos, *cend; 1247 int len, nlen, rem, xfer, tsiz, i; 1248 struct vnode *vp; 1249 struct mbuf *mp2, *mp3; 1250 nfsv2fh_t nfh; 1251 fhandle_t *fhp; 1252 struct uio io; 1253 struct iovec iv; 1254 int siz, cnt, fullsiz, eofflag; 1255 u_long on; 1256 char *rbuf; 1257 off_t off, toff; 1258 1259 fhp = &nfh.fh_generic; 1260 nfsm_srvmtofh(fhp); 1261 nfsm_disect(tl, u_long *, 2*NFSX_UNSIGNED); 1262 toff = fxdr_unsigned(off_t, *tl++); 1263 off = (toff & ~(NFS_DIRBLKSIZ-1)); 1264 on = (toff & (NFS_DIRBLKSIZ-1)); 1265 cnt = fxdr_unsigned(int, *tl); 1266 siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1)); 1267 if (cnt > NFS_MAXREADDIR) 1268 siz = NFS_MAXREADDIR; 1269 fullsiz = siz; 1270 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1271 nfsm_reply(0); 1272 if (error = nfsrv_access(vp, VEXEC, cred, p)) { 1273 vput(vp); 1274 nfsm_reply(0); 1275 } 1276 VOP_UNLOCK(vp); 1277 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1278 again: 1279 iv.iov_base = rbuf; 1280 iv.iov_len = fullsiz; 1281 io.uio_iov = &iv; 1282 io.uio_iovcnt = 1; 1283 io.uio_offset = off; 1284 io.uio_resid = fullsiz; 1285 io.uio_segflg = UIO_SYSSPACE; 1286 io.uio_rw = UIO_READ; 1287 io.uio_procp = (struct proc *)0; 1288 error = VOP_READDIR(vp, &io, cred, &eofflag); 1289 off = io.uio_offset; 1290 if (error) { 1291 vrele(vp); 1292 free((caddr_t)rbuf, M_TEMP); 1293 nfsm_reply(0); 1294 } 1295 if (io.uio_resid) { 1296 siz -= io.uio_resid; 1297 1298 /* 1299 * If nothing read, return eof 1300 * rpc reply 1301 */ 1302 if (siz == 0) { 1303 vrele(vp); 1304 nfsm_reply(2*NFSX_UNSIGNED); 1305 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 1306 *tl++ = nfs_false; 1307 *tl = nfs_true; 1308 FREE((caddr_t)rbuf, M_TEMP); 1309 return (0); 1310 } 1311 } 1312 1313 /* 1314 * Check for degenerate cases of nothing useful read. 1315 * If so go try again 1316 */ 1317 cpos = rbuf + on; 1318 cend = rbuf + siz; 1319 dp = (struct direct *)cpos; 1320 while (cpos < cend && dp->d_ino == 0) { 1321 cpos += dp->d_reclen; 1322 dp = (struct direct *)cpos; 1323 } 1324 if (cpos >= cend) { 1325 toff = off; 1326 siz = fullsiz; 1327 on = 0; 1328 goto again; 1329 } 1330 1331 cpos = rbuf + on; 1332 cend = rbuf + siz; 1333 dp = (struct direct *)cpos; 1334 vrele(vp); 1335 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 1336 bp = be = (caddr_t)0; 1337 mp3 = (struct mbuf *)0; 1338 nfsm_reply(siz); 1339 1340 /* Loop through the records and build reply */ 1341 while (cpos < cend) { 1342 if (dp->d_ino != 0) { 1343 nlen = dp->d_namlen; 1344 rem = nfsm_rndup(nlen)-nlen; 1345 1346 /* 1347 * As noted above, the NFS spec. is not clear about what 1348 * should be included in "count" as totalled up here in 1349 * "len". 1350 */ 1351 len += (4*NFSX_UNSIGNED+nlen+rem); 1352 if (len > cnt) { 1353 eofflag = 0; 1354 break; 1355 } 1356 1357 /* Build the directory record xdr from the direct entry */ 1358 nfsm_clget; 1359 *tl = nfs_true; 1360 bp += NFSX_UNSIGNED; 1361 nfsm_clget; 1362 *tl = txdr_unsigned(dp->d_ino); 1363 bp += NFSX_UNSIGNED; 1364 nfsm_clget; 1365 *tl = txdr_unsigned(nlen); 1366 bp += NFSX_UNSIGNED; 1367 1368 /* And loop arround copying the name */ 1369 xfer = nlen; 1370 cp = dp->d_name; 1371 while (xfer > 0) { 1372 nfsm_clget; 1373 if ((bp+xfer) > be) 1374 tsiz = be-bp; 1375 else 1376 tsiz = xfer; 1377 bcopy(cp, bp, tsiz); 1378 bp += tsiz; 1379 xfer -= tsiz; 1380 if (xfer > 0) 1381 cp += tsiz; 1382 } 1383 /* And null pad to a long boundary */ 1384 for (i = 0; i < rem; i++) 1385 *bp++ = '\0'; 1386 nfsm_clget; 1387 1388 /* Finish off the record */ 1389 toff += dp->d_reclen; 1390 *tl = txdr_unsigned(toff); 1391 bp += NFSX_UNSIGNED; 1392 } else 1393 toff += dp->d_reclen; 1394 cpos += dp->d_reclen; 1395 dp = (struct direct *)cpos; 1396 } 1397 nfsm_clget; 1398 *tl = nfs_false; 1399 bp += NFSX_UNSIGNED; 1400 nfsm_clget; 1401 if (eofflag) 1402 *tl = nfs_true; 1403 else 1404 *tl = nfs_false; 1405 bp += NFSX_UNSIGNED; 1406 if (bp < be) 1407 mp->m_len = bp-mtod(mp, caddr_t); 1408 mb->m_next = mp3; 1409 FREE(rbuf, M_TEMP); 1410 nfsm_srvdone; 1411 } 1412 1413 /* 1414 * nfs statfs service 1415 */ 1416 nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat, p) 1417 struct mbuf **mrq; 1418 struct mbuf *mrep, *md; 1419 caddr_t dpos; 1420 struct ucred *cred; 1421 u_long xid; 1422 int *repstat; 1423 struct proc *p; 1424 { 1425 register struct statfs *sf; 1426 register struct nfsv2_statfs *sfp; 1427 register u_long *tl; 1428 register long t1; 1429 caddr_t bpos; 1430 int error = 0; 1431 char *cp2; 1432 struct mbuf *mb, *mb2, *mreq; 1433 struct vnode *vp; 1434 nfsv2fh_t nfh; 1435 fhandle_t *fhp; 1436 struct statfs statfs; 1437 1438 fhp = &nfh.fh_generic; 1439 nfsm_srvmtofh(fhp); 1440 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1441 nfsm_reply(0); 1442 sf = &statfs; 1443 error = VFS_STATFS(vp->v_mount, sf, p); 1444 vput(vp); 1445 nfsm_reply(NFSX_STATFS); 1446 nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS); 1447 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 1448 sfp->sf_bsize = txdr_unsigned(sf->f_fsize); 1449 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 1450 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 1451 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 1452 nfsm_srvdone; 1453 } 1454 1455 /* 1456 * Null operation, used by clients to ping server 1457 */ 1458 /* ARGSUSED */ 1459 nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat, p) 1460 struct mbuf **mrq; 1461 struct mbuf *mrep, *md; 1462 caddr_t dpos; 1463 struct ucred *cred; 1464 u_long xid; 1465 int *repstat; 1466 struct proc *p; 1467 { 1468 caddr_t bpos; 1469 int error = 0; 1470 struct mbuf *mb, *mreq; 1471 1472 error = VNOVAL; 1473 nfsm_reply(0); 1474 return (error); 1475 } 1476 1477 /* 1478 * No operation, used for obsolete procedures 1479 */ 1480 /* ARGSUSED */ 1481 nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat, p) 1482 struct mbuf **mrq; 1483 struct mbuf *mrep, *md; 1484 caddr_t dpos; 1485 struct ucred *cred; 1486 u_long xid; 1487 int *repstat; 1488 struct proc *p; 1489 { 1490 caddr_t bpos; 1491 int error; /* 08 Sep 92*/ 1492 struct mbuf *mb, *mreq; 1493 1494 if (*repstat) /* 08 Sep 92*/ 1495 error = *repstat; 1496 else 1497 error = EPROCUNAVAIL; 1498 nfsm_reply(0); 1499 return (error); 1500 } 1501 1502 /* 1503 * Perform access checking for vnodes obtained from file handles that would 1504 * refer to files already opened by a Unix client. You cannot just use 1505 * vn_writechk() and VOP_ACCESS() for two reasons. 1506 * 1 - You must check for MNT_EXRDONLY as well as MNT_RDONLY for the write case 1507 * 2 - The owner is to be given access irrespective of mode bits so that 1508 * processes that chmod after opening a file don't break. I don't like 1509 * this because it opens a security hole, but since the nfs server opens 1510 * a security hole the size of a barn door anyhow, what the heck. 1511 */ 1512 nfsrv_access(vp, flags, cred, p) 1513 register struct vnode *vp; 1514 int flags; 1515 register struct ucred *cred; 1516 struct proc *p; 1517 { 1518 struct vattr vattr; 1519 int error; 1520 if (flags & VWRITE) { 1521 /* Just vn_writechk() changed to check MNT_EXRDONLY */ 1522 /* 1523 * Disallow write attempts on read-only file systems; 1524 * unless the file is a socket or a block or character 1525 * device resident on the file system. 1526 */ 1527 if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) { 1528 switch (vp->v_type) { 1529 case VREG: case VDIR: case VLNK: 1530 return (EROFS); 1531 } 1532 } 1533 /* 1534 * If there's shared text associated with 1535 * the inode, try to free it up once. If 1536 * we fail, we can't allow writing. 1537 */ 1538 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 1539 return (ETXTBSY); 1540 } 1541 if (error = VOP_GETATTR(vp, &vattr, cred, p)) 1542 return (error); 1543 if ((error = VOP_ACCESS(vp, flags, cred, p)) && 1544 cred->cr_uid != vattr.va_uid) 1545 return (error); 1546 return (0); 1547 } 1548