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