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