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