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