1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * @(#)nfs_serv.c 7.7 (Berkeley) 08/30/89 21 */ 22 23 /* 24 * nfs version 2 server calls to vnode ops 25 * - these routines generally have 3 phases 26 * 1 - break down and validate rpc request in mbuf list 27 * 2 - do the vnode ops for the request 28 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c) 29 * 3 - build the rpc reply in an mbuf list 30 * nb: 31 * - do not mix the phases, since the nfsm_?? macros can return failures 32 * on mbuf exhaustion or similar and do not do any vrele() or vput()'s 33 * 34 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs 35 * error number iff error != 0 whereas 36 * nfsm_srverr simply drops the mbufs and gives up 37 * (==> nfsm_srverr implies an error here at the server, usually mbuf 38 * exhaustion) 39 */ 40 41 #include "strings.h" 42 #include "time.h" 43 #include "param.h" 44 #include "mount.h" 45 #include "malloc.h" 46 #include "mbuf.h" 47 #include "file.h" 48 #include "user.h" 49 #include "../ufs/dir.h" 50 #include "vnode.h" 51 #include "uio.h" 52 #include "ucred.h" 53 #include "namei.h" 54 #include "errno.h" 55 #include "../ufs/inode.h" 56 #include "nfsv2.h" 57 #include "nfs.h" 58 #include "xdr_subs.h" 59 #include "nfsm_subs.h" 60 61 /* Defs */ 62 #define TRUE 1 63 #define FALSE 0 64 65 /* Global vars */ 66 extern u_long nfs_procids[NFS_NPROCS]; 67 extern u_long nfs_xdrneg1; 68 extern u_long nfs_false, nfs_true; 69 nfstype nfs_type[VSOCK+1]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, }; 70 71 /* 72 * nfs getattr service 73 */ 74 nfsrv_getattr(mrep, md, dpos, cred, xid, mrq) 75 struct mbuf **mrq; 76 struct mbuf *mrep, *md; 77 caddr_t dpos; 78 struct ucred *cred; 79 u_long xid; 80 { 81 register struct nfsv2_fattr *fp; 82 struct vattr va; 83 register struct vattr *vap = &va; 84 struct vnode *vp; 85 nfsv2fh_t nfh; 86 fhandle_t *fhp; 87 nfsm_srvars; 88 89 fhp = &nfh.fh_generic; 90 nfsm_srvmtofh(fhp); 91 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 92 nfsm_reply(0); 93 error = VOP_GETATTR(vp, vap, cred); 94 vput(vp); 95 nfsm_reply(NFSX_FATTR); 96 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 97 fp->fa_type = vtonfs_type(vap->va_type); 98 fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 99 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 100 fp->fa_uid = txdr_unsigned(vap->va_uid); 101 fp->fa_gid = txdr_unsigned(vap->va_gid); 102 fp->fa_size = txdr_unsigned(vap->va_size); 103 fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); 104 fp->fa_rdev = txdr_unsigned(vap->va_rdev); 105 fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize); 106 fp->fa_fsid = txdr_unsigned(vap->va_fsid); 107 fp->fa_fileid = txdr_unsigned(vap->va_fileid); 108 txdr_time(&vap->va_atime, &fp->fa_atime); 109 txdr_time(&vap->va_mtime, &fp->fa_mtime); 110 txdr_time(&vap->va_ctime, &fp->fa_ctime); 111 nfsm_srvdone; 112 } 113 114 /* 115 * nfs setattr service 116 */ 117 nfsrv_setattr(mrep, md, dpos, cred, xid, mrq) 118 struct mbuf **mrq; 119 struct mbuf *mrep, *md; 120 caddr_t dpos; 121 struct ucred *cred; 122 u_long xid; 123 { 124 struct vattr va; 125 register struct vattr *vap = &va; 126 register struct nfsv2_sattr *sp; 127 register struct nfsv2_fattr *fp; 128 struct vnode *vp; 129 nfsv2fh_t nfh; 130 fhandle_t *fhp; 131 nfsm_srvars; 132 133 fhp = &nfh.fh_generic; 134 nfsm_srvmtofh(fhp); 135 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); 136 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 137 nfsm_reply(0); 138 if (error = nfsrv_access(vp, VWRITE, cred)) 139 goto out; 140 vattr_null(vap); 141 /* 142 * Nah nah nah nah na nah 143 * There is a bug in the Sun client that puts 0xffff in the mode 144 * field of sattr when it should put in 0xffffffff. The u_short 145 * doesn't sign extend. 146 * --> check the low order 2 bytes for 0xffff 147 */ 148 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 149 vap->va_mode = nfstov_mode(sp->sa_mode); 150 if (sp->sa_uid != nfs_xdrneg1) 151 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid); 152 if (sp->sa_gid != nfs_xdrneg1) 153 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid); 154 if (sp->sa_size != nfs_xdrneg1) { 155 vap->va_size = fxdr_unsigned(u_long, sp->sa_size); 156 } 157 if (sp->sa_atime.tv_sec != nfs_xdrneg1) 158 fxdr_time(&sp->sa_atime, &vap->va_atime); 159 if (sp->sa_mtime.tv_sec != nfs_xdrneg1) 160 fxdr_time(&sp->sa_mtime, &vap->va_mtime); 161 if (error = VOP_SETATTR(vp, vap, cred)) { 162 vput(vp); 163 nfsm_reply(0); 164 } 165 error = VOP_GETATTR(vp, vap, cred); 166 out: 167 vput(vp); 168 nfsm_reply(NFSX_FATTR); 169 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 170 fp->fa_type = vtonfs_type(vap->va_type); 171 fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 172 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 173 fp->fa_uid = txdr_unsigned(vap->va_uid); 174 fp->fa_gid = txdr_unsigned(vap->va_gid); 175 fp->fa_size = txdr_unsigned(vap->va_size); 176 fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); 177 fp->fa_rdev = txdr_unsigned(vap->va_rdev); 178 fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize); 179 fp->fa_fsid = txdr_unsigned(vap->va_fsid); 180 fp->fa_fileid = txdr_unsigned(vap->va_fileid); 181 txdr_time(&vap->va_atime, &fp->fa_atime); 182 txdr_time(&vap->va_mtime, &fp->fa_mtime); 183 txdr_time(&vap->va_ctime, &fp->fa_ctime); 184 nfsm_srvdone; 185 } 186 187 /* 188 * nfs lookup rpc 189 */ 190 nfsrv_lookup(mrep, md, dpos, cred, xid, mrq) 191 struct mbuf **mrq; 192 struct mbuf *mrep, *md; 193 caddr_t dpos; 194 struct ucred *cred; 195 u_long xid; 196 { 197 register struct nfsv2_fattr *fp; 198 register struct nameidata *ndp = &u.u_nd; 199 struct vnode *vp; 200 nfsv2fh_t nfh; 201 fhandle_t *fhp; 202 nfsm_srvars; 203 long len; 204 struct vattr va, *vap = &va; 205 206 fhp = &nfh.fh_generic; 207 nfsm_srvmtofh(fhp); 208 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 209 ndp->ni_cred = cred; 210 ndp->ni_nameiop = LOOKUP | LOCKLEAF; 211 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 212 nfsm_reply(0); 213 vp = ndp->ni_vp; 214 bzero((caddr_t)fhp, sizeof(nfh)); 215 fhp->fh_fsid = vp->v_mount->m_fsid; 216 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 217 vput(vp); 218 nfsm_reply(0); 219 } 220 error = VOP_GETATTR(vp, vap, cred); 221 vput(vp); 222 nfsm_reply(NFSX_FH+NFSX_FATTR); 223 nfsm_srvfhtom(fhp); 224 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 225 fp->fa_type = vtonfs_type(vap->va_type); 226 fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 227 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 228 fp->fa_uid = txdr_unsigned(vap->va_uid); 229 fp->fa_gid = txdr_unsigned(vap->va_gid); 230 fp->fa_size = txdr_unsigned(vap->va_size); 231 fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); 232 fp->fa_rdev = txdr_unsigned(vap->va_rdev); 233 fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize); 234 fp->fa_fsid = txdr_unsigned(vap->va_fsid); 235 fp->fa_fileid = txdr_unsigned(vap->va_fileid); 236 txdr_time(&vap->va_atime, &fp->fa_atime); 237 txdr_time(&vap->va_mtime, &fp->fa_mtime); 238 txdr_time(&vap->va_ctime, &fp->fa_ctime); 239 nfsm_srvdone; 240 } 241 242 /* 243 * nfs readlink service 244 */ 245 nfsrv_readlink(mrep, md, dpos, cred, xid, mrq) 246 struct mbuf **mrq; 247 struct mbuf *mrep, *md; 248 caddr_t dpos; 249 struct ucred *cred; 250 long xid; 251 { 252 struct iovec iv[NFS_MAXPATHLEN/MLEN+1]; 253 register struct iovec *ivp = iv; 254 register struct mbuf *mp; 255 nfsm_srvars; 256 struct mbuf *mp2, *mp3; 257 struct vnode *vp; 258 nfsv2fh_t nfh; 259 fhandle_t *fhp; 260 struct uio io, *uiop = &io; 261 int i, tlen, len; 262 263 fhp = &nfh.fh_generic; 264 nfsm_srvmtofh(fhp); 265 len = 0; 266 i = 0; 267 while (len < NFS_MAXPATHLEN) { 268 MGET(mp, M_WAIT, MT_DATA); 269 NFSMCLGET(mp, M_WAIT); 270 mp->m_len = NFSMSIZ(mp); 271 if (len == 0) 272 mp3 = mp2 = mp; 273 else 274 mp2->m_next = mp; 275 if ((len+mp->m_len) > NFS_MAXPATHLEN) { 276 mp->m_len = NFS_MAXPATHLEN-len; 277 len = NFS_MAXPATHLEN; 278 } else 279 len += mp->m_len; 280 ivp->iov_base = mtod(mp, caddr_t); 281 ivp->iov_len = mp->m_len; 282 i++; 283 ivp++; 284 } 285 uiop->uio_iov = iv; 286 uiop->uio_iovcnt = i; 287 uiop->uio_offset = 0; 288 uiop->uio_resid = len; 289 uiop->uio_rw = UIO_READ; 290 uiop->uio_segflg = UIO_SYSSPACE; 291 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) { 292 m_freem(mp3); 293 nfsm_reply(0); 294 } 295 if (vp->v_type != VLNK) { 296 error = EINVAL; 297 goto out; 298 } 299 error = VOP_READLINK(vp, uiop, cred); 300 out: 301 vput(vp); 302 if (error) 303 m_freem(mp3); 304 nfsm_reply(NFSX_UNSIGNED); 305 if (uiop->uio_resid > 0) { 306 len -= uiop->uio_resid; 307 tlen = nfsm_rndup(len); 308 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len); 309 } 310 nfsm_build(p, u_long *, NFSX_UNSIGNED); 311 *p = txdr_unsigned(len); 312 mb->m_next = mp3; 313 nfsm_srvdone; 314 } 315 316 /* 317 * nfs read service 318 */ 319 nfsrv_read(mrep, md, dpos, cred, xid, mrq) 320 struct mbuf **mrq; 321 struct mbuf *mrep, *md; 322 caddr_t dpos; 323 struct ucred *cred; 324 u_long xid; 325 { 326 struct iovec iv[NFS_MAXDATA/MCLBYTES+1]; 327 register struct iovec *ivp = iv; 328 register struct mbuf *mp; 329 register struct nfsv2_fattr *fp; 330 nfsm_srvars; 331 struct mbuf *mp2, *mp3; 332 struct vnode *vp; 333 nfsv2fh_t nfh; 334 fhandle_t *fhp; 335 struct uio io, *uiop = &io; 336 struct vattr va, *vap = &va; 337 int i, tlen, cnt, len, nio, left; 338 off_t off; 339 340 fhp = &nfh.fh_generic; 341 nfsm_srvmtofh(fhp); 342 nfsm_disect(p, u_long *, NFSX_UNSIGNED); 343 off = fxdr_unsigned(off_t, *p); 344 nfsm_srvstrsiz(cnt, NFS_MAXDATA); 345 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 346 nfsm_reply(0); 347 if (error = nfsrv_access(vp, VREAD | VEXEC, cred)) { 348 vput(vp); 349 nfsm_reply(0); 350 } 351 len = left = cnt; 352 nio = (cnt+MCLBYTES-1)/MCLBYTES; 353 uiop->uio_iov = ivp; 354 uiop->uio_iovcnt = nio; 355 uiop->uio_offset = off; 356 uiop->uio_resid = cnt; 357 uiop->uio_rw = UIO_READ; 358 uiop->uio_segflg = UIO_SYSSPACE; 359 for (i = 0; i < nio; i++) { 360 MGET(mp, M_WAIT, MT_DATA); 361 if (left > MLEN) 362 NFSMCLGET(mp, M_WAIT); 363 mp->m_len = (M_HASCL(mp)) ? MCLBYTES : MLEN; 364 if (i == 0) { 365 mp3 = mp2 = mp; 366 } else { 367 mp2->m_next = mp; 368 mp2 = mp; 369 } 370 if (left > MLEN && !M_HASCL(mp)) { 371 m_freem(mp3); 372 vput(vp); 373 nfsm_srverr; 374 } 375 ivp->iov_base = mtod(mp, caddr_t); 376 if (left > mp->m_len) { 377 ivp->iov_len = mp->m_len; 378 left -= mp->m_len; 379 } else { 380 ivp->iov_len = mp->m_len = left; 381 left = 0; 382 } 383 ivp++; 384 } 385 error = VOP_READ(vp, uiop, &off, IO_NODELOCKED, cred); 386 if (error) { 387 m_freem(mp3); 388 vput(vp); 389 nfsm_reply(0); 390 } 391 if (error = VOP_GETATTR(vp, vap, cred)) 392 m_freem(mp3); 393 vput(vp); 394 nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED); 395 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 396 fp->fa_type = vtonfs_type(vap->va_type); 397 fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 398 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 399 fp->fa_uid = txdr_unsigned(vap->va_uid); 400 fp->fa_gid = txdr_unsigned(vap->va_gid); 401 fp->fa_size = txdr_unsigned(vap->va_size); 402 fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); 403 fp->fa_rdev = txdr_unsigned(vap->va_rdev); 404 fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize); 405 fp->fa_fsid = txdr_unsigned(vap->va_fsid); 406 fp->fa_fileid = txdr_unsigned(vap->va_fileid); 407 txdr_time(&vap->va_atime, &fp->fa_atime); 408 txdr_time(&vap->va_mtime, &fp->fa_mtime); 409 txdr_time(&vap->va_ctime, &fp->fa_ctime); 410 if (uiop->uio_resid > 0) { 411 len -= uiop->uio_resid; 412 if (len > 0) { 413 tlen = nfsm_rndup(len); 414 nfsm_adj(mp3, cnt-tlen, tlen-len); 415 } else { 416 m_freem(mp3); 417 mp3 = (struct mbuf *)0; 418 } 419 } 420 nfsm_build(p, u_long *, NFSX_UNSIGNED); 421 *p = txdr_unsigned(len); 422 mb->m_next = mp3; 423 nfsm_srvdone; 424 } 425 426 /* 427 * nfs write service 428 */ 429 nfsrv_write(mrep, md, dpos, cred, xid, mrq) 430 struct mbuf *mrep, *md, **mrq; 431 caddr_t dpos; 432 struct ucred *cred; 433 long xid; 434 { 435 register struct iovec *ivp; 436 register struct mbuf *mp; 437 register struct nfsv2_fattr *fp; 438 struct iovec iv[MAX_IOVEC]; 439 struct vattr va; 440 register struct vattr *vap = &va; 441 nfsm_srvars; 442 struct vnode *vp; 443 nfsv2fh_t nfh; 444 fhandle_t *fhp; 445 struct uio io, *uiop = &io; 446 off_t off; 447 long siz, len, xfer; 448 449 fhp = &nfh.fh_generic; 450 nfsm_srvmtofh(fhp); 451 nfsm_disect(p, u_long *, 4*NFSX_UNSIGNED); 452 off = fxdr_unsigned(off_t, *++p); 453 p += 2; 454 len = fxdr_unsigned(long, *p); 455 if (len > NFS_MAXDATA || len <= 0) { 456 error = EBADRPC; 457 nfsm_reply(0); 458 } 459 if (dpos == (mtod(md, caddr_t)+md->m_len)) { 460 mp = md->m_next; 461 if (mp == NULL) { 462 error = EBADRPC; 463 nfsm_reply(0); 464 } 465 } else { 466 mp = md; 467 siz = dpos-mtod(mp, caddr_t); 468 mp->m_len -= siz; 469 NFSMADV(mp, siz); 470 } 471 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 472 nfsm_reply(0); 473 if (error = nfsrv_access(vp, VWRITE, cred)) { 474 vput(vp); 475 nfsm_reply(0); 476 } 477 uiop->uio_resid = 0; 478 uiop->uio_rw = UIO_WRITE; 479 uiop->uio_segflg = UIO_SYSSPACE; 480 /* 481 * Do up to MAX_IOVEC mbufs of write each iteration of the 482 * loop until done. 483 */ 484 while (len > 0 && uiop->uio_resid == 0) { 485 ivp = iv; 486 siz = 0; 487 uiop->uio_iov = ivp; 488 uiop->uio_iovcnt = 0; 489 uiop->uio_offset = off; 490 while (len > 0 && uiop->uio_iovcnt < MAX_IOVEC && mp != NULL) { 491 ivp->iov_base = mtod(mp, caddr_t); 492 if (len < mp->m_len) 493 ivp->iov_len = xfer = len; 494 else 495 ivp->iov_len = xfer = mp->m_len; 496 #ifdef notdef 497 /* Not Yet .. */ 498 if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0) 499 ivp->iov_op = NULL; /* what should it be ?? */ 500 else 501 ivp->iov_op = NULL; 502 #endif 503 uiop->uio_iovcnt++; 504 ivp++; 505 len -= xfer; 506 siz += xfer; 507 mp = mp->m_next; 508 } 509 if (len > 0 && mp == NULL) { 510 error = EBADRPC; 511 vput(vp); 512 nfsm_reply(0); 513 } 514 uiop->uio_resid = siz; 515 if (error = VOP_WRITE(vp, uiop, &off, IO_SYNC | IO_NODELOCKED, 516 cred)) { 517 vput(vp); 518 nfsm_reply(0); 519 } 520 } 521 error = VOP_GETATTR(vp, vap, cred); 522 vput(vp); 523 nfsm_reply(NFSX_FATTR); 524 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 525 fp->fa_type = vtonfs_type(vap->va_type); 526 fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 527 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 528 fp->fa_uid = txdr_unsigned(vap->va_uid); 529 fp->fa_gid = txdr_unsigned(vap->va_gid); 530 fp->fa_size = txdr_unsigned(vap->va_size); 531 fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); 532 fp->fa_rdev = txdr_unsigned(vap->va_rdev); 533 fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize); 534 fp->fa_fsid = txdr_unsigned(vap->va_fsid); 535 fp->fa_fileid = txdr_unsigned(vap->va_fileid); 536 txdr_time(&vap->va_atime, &fp->fa_atime); 537 txdr_time(&vap->va_mtime, &fp->fa_mtime); 538 txdr_time(&vap->va_ctime, &fp->fa_ctime); 539 nfsm_srvdone; 540 } 541 542 /* 543 * nfs create service 544 * now does a truncate to 0 length via. setattr if it already exists 545 */ 546 nfsrv_create(mrep, md, dpos, cred, xid, mrq) 547 struct mbuf *mrep, *md, **mrq; 548 caddr_t dpos; 549 struct ucred *cred; 550 long xid; 551 { 552 register struct nfsv2_fattr *fp; 553 struct vattr va; 554 register struct vattr *vap = &va; 555 register struct nameidata *ndp = &u.u_nd; 556 nfsm_srvars; 557 struct vnode *vp; 558 nfsv2fh_t nfh; 559 fhandle_t *fhp; 560 long len; 561 562 ndp->ni_vp = ndp->ni_dvp = (struct vnode *)0; 563 fhp = &nfh.fh_generic; 564 nfsm_srvmtofh(fhp); 565 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 566 ndp->ni_cred = cred; 567 ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 568 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 569 nfsm_reply(0); 570 vattr_null(vap); 571 nfsm_disect(p, u_long *, NFSX_UNSIGNED); 572 /* 573 * Iff doesn't exist, create it 574 * otherwise just truncate to 0 length 575 * should I set the mode too ?? 576 */ 577 if (ndp->ni_vp == NULL) { 578 vap->va_type = VREG; 579 vap->va_mode = nfstov_mode(*p++); 580 if (error = VOP_CREATE(ndp, vap)) 581 nfsm_reply(0); 582 vp = ndp->ni_vp; 583 } else { 584 vp = ndp->ni_vp; 585 ndp->ni_vp = (struct vnode *)0; 586 VOP_ABORTOP(ndp); 587 vap->va_size = 0; 588 if (error = VOP_SETATTR(vp, vap, cred)) 589 nfsm_reply(0); 590 } 591 bzero((caddr_t)fhp, sizeof(nfh)); 592 fhp->fh_fsid = vp->v_mount->m_fsid; 593 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 594 vput(vp); 595 nfsm_reply(0); 596 } 597 error = VOP_GETATTR(vp, vap, cred); 598 vput(vp); 599 nfsm_reply(NFSX_FH+NFSX_FATTR); 600 nfsm_srvfhtom(fhp); 601 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 602 fp->fa_type = vtonfs_type(vap->va_type); 603 fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 604 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 605 fp->fa_uid = txdr_unsigned(vap->va_uid); 606 fp->fa_gid = txdr_unsigned(vap->va_gid); 607 fp->fa_size = txdr_unsigned(vap->va_size); 608 fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); 609 fp->fa_rdev = txdr_unsigned(vap->va_rdev); 610 fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize); 611 fp->fa_fsid = txdr_unsigned(vap->va_fsid); 612 fp->fa_fileid = txdr_unsigned(vap->va_fileid); 613 txdr_time(&vap->va_atime, &fp->fa_atime); 614 txdr_time(&vap->va_mtime, &fp->fa_mtime); 615 txdr_time(&vap->va_ctime, &fp->fa_ctime); 616 return (error); 617 nfsmout: 618 VOP_ABORTOP(ndp); 619 return (error); 620 } 621 622 /* 623 * nfs remove service 624 */ 625 nfsrv_remove(mrep, md, dpos, cred, xid, mrq) 626 struct mbuf *mrep, *md, **mrq; 627 caddr_t dpos; 628 struct ucred *cred; 629 long xid; 630 { 631 register struct nameidata *ndp = &u.u_nd; 632 nfsm_srvars; 633 struct vnode *vp; 634 nfsv2fh_t nfh; 635 fhandle_t *fhp; 636 long len; 637 638 fhp = &nfh.fh_generic; 639 nfsm_srvmtofh(fhp); 640 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 641 ndp->ni_cred = cred; 642 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 643 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 644 nfsm_reply(0); 645 vp = ndp->ni_vp; 646 if (vp->v_type == VDIR && 647 (error = suser(cred, (short *)0))) 648 goto out; 649 /* 650 * Don't unlink a mounted file. 651 */ 652 if (vp->v_flag & VROOT) { 653 error = EBUSY; 654 goto out; 655 } 656 if (vp->v_flag & VTEXT) 657 xrele(vp); /* try once to free text */ 658 out: 659 if (error) 660 VOP_ABORTOP(ndp); 661 else 662 error = VOP_REMOVE(ndp); 663 nfsm_reply(0); 664 nfsm_srvdone; 665 } 666 667 /* 668 * nfs rename service 669 */ 670 nfsrv_rename(mrep, md, dpos, cred, xid, mrq) 671 struct mbuf *mrep, *md, **mrq; 672 caddr_t dpos; 673 struct ucred *cred; 674 long xid; 675 { 676 register struct nameidata *ndp; 677 nfsm_srvars; 678 struct nameidata tond; 679 struct vnode *fvp, *tvp, *tdvp; 680 nfsv2fh_t fnfh, tnfh; 681 fhandle_t *ffhp, *tfhp; 682 long len, len2; 683 int rootflg = 0; 684 685 ndp = &u.u_nd; 686 ndp->ni_vp = ndp->ni_dvp = (struct vnode *)0; 687 ffhp = &fnfh.fh_generic; 688 tfhp = &tnfh.fh_generic; 689 nfsm_srvmtofh(ffhp); 690 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 691 /* 692 * Remember if we are root so that we can reset cr_uid before 693 * the second nfs_namei() call 694 */ 695 if (cred->cr_uid == 0) 696 rootflg++; 697 ndp->ni_cred = cred; 698 ndp->ni_nameiop = DELETE | WANTPARENT; 699 if (error = nfs_namei(ndp, ffhp, len, &md, &dpos)) 700 nfsm_reply(0); 701 fvp = ndp->ni_vp; 702 nfsm_srvmtofh(tfhp); 703 nfsm_srvstrsiz(len2, NFS_MAXNAMLEN); 704 if (rootflg) 705 cred->cr_uid = 0; 706 nddup(ndp, &tond); 707 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; 708 error = nfs_namei(&tond, tfhp, len2, &md, &dpos); 709 tdvp = tond.ni_dvp; 710 tvp = tond.ni_vp; 711 if (tvp != NULL) { 712 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 713 error = EISDIR; 714 goto out; 715 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 716 error = ENOTDIR; 717 goto out; 718 } 719 } 720 if (error) { 721 VOP_ABORTOP(ndp); 722 goto out1; 723 } 724 if (fvp->v_mount != tdvp->v_mount) { 725 error = EXDEV; 726 goto out; 727 } 728 if (fvp == tdvp || fvp == tvp) 729 error = EINVAL; 730 out: 731 if (error) { 732 VOP_ABORTOP(&tond); 733 VOP_ABORTOP(ndp); 734 } else { 735 VREF(tond.ni_cdir); 736 error = VOP_RENAME(ndp, &tond); 737 vrele(tond.ni_cdir); 738 } 739 out1: 740 ndrele(ndp); 741 nfsm_reply(0); 742 return (error); 743 nfsmout: 744 VOP_ABORTOP(ndp); 745 return (error); 746 } 747 748 /* 749 * nfs link service 750 */ 751 nfsrv_link(mrep, md, dpos, cred, xid, mrq) 752 struct mbuf *mrep, *md, **mrq; 753 caddr_t dpos; 754 struct ucred *cred; 755 long xid; 756 { 757 register struct nameidata *ndp = &u.u_nd; 758 nfsm_srvars; 759 struct vnode *vp, *xp; 760 nfsv2fh_t nfh, dnfh; 761 fhandle_t *fhp, *dfhp; 762 long len; 763 764 fhp = &nfh.fh_generic; 765 dfhp = &dnfh.fh_generic; 766 nfsm_srvmtofh(fhp); 767 nfsm_srvmtofh(dfhp); 768 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 769 if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred)) 770 nfsm_reply(0); 771 if (vp->v_type == VDIR && (error = suser(cred, NULL))) 772 goto out1; 773 ndp->ni_cred = cred; 774 ndp->ni_nameiop = CREATE | LOCKPARENT; 775 if (error = nfs_namei(ndp, dfhp, len, &md, &dpos)) 776 goto out1; 777 xp = ndp->ni_vp; 778 if (xp != NULL) { 779 error = EEXIST; 780 goto out; 781 } 782 xp = ndp->ni_dvp; 783 if (vp->v_mount != xp->v_mount) 784 error = EXDEV; 785 out: 786 if (error) 787 VOP_ABORTOP(ndp); 788 else 789 error = VOP_LINK(vp, ndp); 790 out1: 791 vrele(vp); 792 nfsm_reply(0); 793 nfsm_srvdone; 794 } 795 796 /* 797 * nfs symbolic link service 798 */ 799 nfsrv_symlink(mrep, md, dpos, cred, xid, mrq) 800 struct mbuf *mrep, *md, **mrq; 801 caddr_t dpos; 802 struct ucred *cred; 803 long xid; 804 { 805 struct vattr va; 806 register struct nameidata *ndp = &u.u_nd; 807 register struct vattr *vap = &va; 808 nfsm_srvars; 809 struct vnode *vp; 810 nfsv2fh_t nfh; 811 fhandle_t *fhp; 812 long len, tlen, len2; 813 814 ndp->ni_vp = ndp->ni_dvp = (struct vnode *)0; 815 fhp = &nfh.fh_generic; 816 nfsm_srvmtofh(fhp); 817 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 818 ndp->ni_cred = cred; 819 ndp->ni_nameiop = CREATE | LOCKPARENT; 820 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 821 goto out1; 822 nfsm_srvstrsiz(len2, NFS_MAXPATHLEN); 823 tlen = nfsm_rndup(len2); 824 if (len2 == tlen) { 825 nfsm_disect(cp2, caddr_t, tlen+NFSX_UNSIGNED); 826 *(cp2+tlen) = '\0'; 827 } else { 828 nfsm_disect(cp2, caddr_t, tlen); 829 } 830 vp = ndp->ni_vp; 831 if (vp) { 832 error = EEXIST; 833 goto out; 834 } 835 vp = ndp->ni_dvp; 836 vattr_null(vap); 837 vap->va_mode = 0777; 838 out: 839 if (error) 840 VOP_ABORTOP(ndp); 841 else 842 error = VOP_SYMLINK(ndp, vap, cp2); 843 out1: 844 nfsm_reply(0); 845 return (error); 846 nfsmout: 847 VOP_ABORTOP(ndp); 848 return (error); 849 } 850 851 /* 852 * nfs mkdir service 853 */ 854 nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq) 855 struct mbuf *mrep, *md, **mrq; 856 caddr_t dpos; 857 struct ucred *cred; 858 long xid; 859 { 860 struct vattr va; 861 register struct vattr *vap = &va; 862 register struct nfsv2_fattr *fp; 863 register struct nameidata *ndp = &u.u_nd; 864 nfsm_srvars; 865 struct vnode *vp; 866 nfsv2fh_t nfh; 867 fhandle_t *fhp; 868 long len; 869 870 ndp->ni_vp = ndp->ni_dvp = (struct vnode *)0; 871 fhp = &nfh.fh_generic; 872 nfsm_srvmtofh(fhp); 873 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 874 ndp->ni_cred = cred; 875 ndp->ni_nameiop = CREATE | LOCKPARENT; 876 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 877 nfsm_reply(0); 878 nfsm_disect(p, u_long *, NFSX_UNSIGNED); 879 vattr_null(vap); 880 vap->va_type = VDIR; 881 vap->va_mode = nfstov_mode(*p++); 882 vp = ndp->ni_vp; 883 if (vp != NULL) { 884 VOP_ABORTOP(ndp); 885 error = EEXIST; 886 nfsm_reply(0); 887 } 888 if (error = VOP_MKDIR(ndp, vap)) 889 nfsm_reply(0); 890 vp = ndp->ni_vp; 891 bzero((caddr_t)fhp, sizeof(nfh)); 892 fhp->fh_fsid = vp->v_mount->m_fsid; 893 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 894 vput(vp); 895 nfsm_reply(0); 896 } 897 error = VOP_GETATTR(vp, vap, cred); 898 vput(vp); 899 nfsm_reply(NFSX_FH+NFSX_FATTR); 900 nfsm_srvfhtom(fhp); 901 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 902 fp->fa_type = vtonfs_type(vap->va_type); 903 fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 904 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 905 fp->fa_uid = txdr_unsigned(vap->va_uid); 906 fp->fa_gid = txdr_unsigned(vap->va_gid); 907 fp->fa_size = txdr_unsigned(vap->va_size); 908 fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); 909 fp->fa_rdev = txdr_unsigned(vap->va_rdev); 910 fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize); 911 fp->fa_fsid = txdr_unsigned(vap->va_fsid); 912 fp->fa_fileid = txdr_unsigned(vap->va_fileid); 913 txdr_time(&vap->va_atime, &fp->fa_atime); 914 txdr_time(&vap->va_mtime, &fp->fa_mtime); 915 txdr_time(&vap->va_ctime, &fp->fa_ctime); 916 return (error); 917 nfsmout: 918 VOP_ABORTOP(ndp); 919 return (error); 920 } 921 922 /* 923 * nfs rmdir service 924 */ 925 nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq) 926 struct mbuf *mrep, *md, **mrq; 927 caddr_t dpos; 928 struct ucred *cred; 929 long xid; 930 { 931 register struct nameidata *ndp = &u.u_nd; 932 nfsm_srvars; 933 struct vnode *vp; 934 nfsv2fh_t nfh; 935 fhandle_t *fhp; 936 long len; 937 938 fhp = &nfh.fh_generic; 939 nfsm_srvmtofh(fhp); 940 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 941 ndp->ni_cred = cred; 942 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 943 if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) 944 nfsm_reply(0); 945 vp = ndp->ni_vp; 946 if (vp->v_type != VDIR) { 947 error = ENOTDIR; 948 goto out; 949 } 950 /* 951 * No rmdir "." please. 952 */ 953 if (ndp->ni_dvp == vp) { 954 error = EINVAL; 955 goto out; 956 } 957 /* 958 * Don't unlink a mounted file. 959 */ 960 if (vp->v_flag & VROOT) 961 error = EBUSY; 962 out: 963 if (error) 964 VOP_ABORTOP(ndp); 965 else 966 error = VOP_RMDIR(ndp); 967 nfsm_reply(0); 968 nfsm_srvdone; 969 } 970 971 /* 972 * nfs readdir service 973 * - mallocs what it thinks is enough to read 974 * count rounded up to a multiple of DIRBLKSIZ <= MAX_READDIR 975 * - calls VOP_READDIR() 976 * - loops arround building the reply 977 * if the output generated exceeds count break out of loop 978 * The nfsm_clget macro is used here so that the reply will be packed 979 * tightly in mbuf clusters. 980 * - it only knows that it has encountered eof when the VOP_READDIR() 981 * reads nothing 982 * - as such one readdir rpc will return eof false although you are there 983 * and then the next will return eof 984 * - it trims out records with d_ino == 0 985 * this doesn't matter for Unix clients, but they might confuse clients 986 * for other os'. 987 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 988 * than requested, but this may not apply to all filesystems. For 989 * example, client NFS does not { although it is never remote mounted 990 * anyhow } 991 * PS: The NFS protocol spec. does not clarify what the "count" byte 992 * argument is a count of.. just name strings and file id's or the 993 * entire reply rpc or ... 994 * I tried just file name and id sizes and it confused the Sun client, 995 * so I am using the full rpc size now. The "paranoia.." comment refers 996 * to including the status longwords that are not a part of the dir. 997 * "entry" structures, but are in the rpc. 998 */ 999 nfsrv_readdir(mrep, md, dpos, cred, xid, mrq) 1000 struct mbuf **mrq; 1001 struct mbuf *mrep, *md; 1002 caddr_t dpos; 1003 struct ucred *cred; 1004 u_long xid; 1005 { 1006 register char *bp, *be; 1007 register struct mbuf *mp; 1008 register struct direct *dp; 1009 nfsm_srvars; 1010 char *cpos, *cend; 1011 int len, nlen, rem, xfer, tsiz, i; 1012 struct vnode *vp; 1013 struct mbuf *mp2, *mp3; 1014 nfsv2fh_t nfh; 1015 fhandle_t *fhp; 1016 struct uio io; 1017 struct iovec iv; 1018 int siz, cnt, fullsiz; 1019 u_long on; 1020 char *rbuf; 1021 off_t off, toff; 1022 1023 fhp = &nfh.fh_generic; 1024 nfsm_srvmtofh(fhp); 1025 nfsm_disect(p, u_long *, 2*NFSX_UNSIGNED); 1026 toff = fxdr_unsigned(off_t, *p++); 1027 off = (toff & ~(DIRBLKSIZ-1)); 1028 on = (toff & (DIRBLKSIZ-1)); 1029 cnt = fxdr_unsigned(int, *p); 1030 siz = ((cnt+DIRBLKSIZ) & ~(DIRBLKSIZ-1)); 1031 if (cnt > MAX_READDIR) 1032 siz = MAX_READDIR; 1033 fullsiz = siz; 1034 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1035 nfsm_reply(0); 1036 if (error = nfsrv_access(vp, VEXEC, cred)) { 1037 vput(vp); 1038 nfsm_reply(0); 1039 } 1040 VOP_UNLOCK(vp); 1041 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1042 again: 1043 iv.iov_base = rbuf; 1044 iv.iov_len = fullsiz; 1045 io.uio_iov = &iv; 1046 io.uio_iovcnt = 1; 1047 io.uio_offset = off; 1048 io.uio_resid = fullsiz; 1049 io.uio_segflg = UIO_SYSSPACE; 1050 io.uio_rw = UIO_READ; 1051 error = VOP_READDIR(vp, &io, &off, cred); 1052 if (error) { 1053 vrele(vp); 1054 free((caddr_t)rbuf, M_TEMP); 1055 nfsm_reply(0); 1056 } 1057 if (io.uio_resid) { 1058 siz -= io.uio_resid; 1059 1060 /* 1061 * If nothing read, return eof 1062 * rpc reply 1063 */ 1064 if (siz == 0) { 1065 vrele(vp); 1066 nfsm_reply(2*NFSX_UNSIGNED); 1067 nfsm_build(p, u_long *, 2*NFSX_UNSIGNED); 1068 *p++ = nfs_false; 1069 *p = nfs_true; 1070 FREE((caddr_t)rbuf, M_TEMP); 1071 return (0); 1072 } 1073 } 1074 cpos = rbuf+on; 1075 cend = rbuf+siz; 1076 dp = (struct direct *)cpos; 1077 /* 1078 * Check for degenerate cases of nothing useful read. 1079 * If so go try again 1080 */ 1081 if (cpos >= cend || (dp->d_ino == 0 && (cpos+dp->d_reclen) >= cend)) { 1082 toff = off; 1083 siz = fullsiz; 1084 on = 0; 1085 goto again; 1086 } 1087 vrele(vp); 1088 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 1089 bp = be = (caddr_t)0; 1090 mp3 = (struct mbuf *)0; 1091 nfsm_reply(siz); 1092 1093 /* Loop through the records and build reply */ 1094 while (cpos < cend) { 1095 if (dp->d_ino != 0) { 1096 nlen = dp->d_namlen; 1097 rem = nfsm_rndup(nlen)-nlen; 1098 1099 /* 1100 * As noted above, the NFS spec. is not clear about what 1101 * should be included in "count" as totalled up here in 1102 * "len". 1103 */ 1104 len += (4*NFSX_UNSIGNED+nlen+rem); 1105 if (len > cnt) 1106 break; 1107 1108 /* Build the directory record xdr from the direct entry */ 1109 nfsm_clget; 1110 *p = nfs_true; 1111 bp += NFSX_UNSIGNED; 1112 nfsm_clget; 1113 *p = txdr_unsigned(dp->d_ino); 1114 bp += NFSX_UNSIGNED; 1115 nfsm_clget; 1116 *p = txdr_unsigned(nlen); 1117 bp += NFSX_UNSIGNED; 1118 1119 /* And loop arround copying the name */ 1120 xfer = nlen; 1121 cp = dp->d_name; 1122 while (xfer > 0) { 1123 nfsm_clget; 1124 if ((bp+xfer) > be) 1125 tsiz = be-bp; 1126 else 1127 tsiz = xfer; 1128 bcopy(cp, bp, tsiz); 1129 bp += tsiz; 1130 xfer -= tsiz; 1131 if (xfer > 0) 1132 cp += tsiz; 1133 } 1134 /* And null pad to a long boundary */ 1135 for (i = 0; i < rem; i++) 1136 *bp++ = '\0'; 1137 nfsm_clget; 1138 1139 /* Finish off the record */ 1140 toff += dp->d_reclen; 1141 *p = txdr_unsigned(toff); 1142 bp += NFSX_UNSIGNED; 1143 } else 1144 toff += dp->d_reclen; 1145 cpos += dp->d_reclen; 1146 dp = (struct direct *)cpos; 1147 } 1148 nfsm_clget; 1149 *p = nfs_false; 1150 bp += NFSX_UNSIGNED; 1151 nfsm_clget; 1152 *p = nfs_false; 1153 bp += NFSX_UNSIGNED; 1154 if (bp < be) 1155 mp->m_len = bp-mtod(mp, caddr_t); 1156 mb->m_next = mp3; 1157 FREE(rbuf, M_TEMP); 1158 nfsm_srvdone; 1159 } 1160 1161 /* 1162 * nfs statfs service 1163 */ 1164 nfsrv_statfs(mrep, md, dpos, cred, xid, mrq) 1165 struct mbuf **mrq; 1166 struct mbuf *mrep, *md; 1167 caddr_t dpos; 1168 struct ucred *cred; 1169 u_long xid; 1170 { 1171 register struct statfs *sf; 1172 register struct nfsv2_statfs *sfp; 1173 nfsm_srvars; 1174 struct vnode *vp; 1175 nfsv2fh_t nfh; 1176 fhandle_t *fhp; 1177 struct statfs statfs; 1178 1179 fhp = &nfh.fh_generic; 1180 nfsm_srvmtofh(fhp); 1181 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1182 nfsm_reply(0); 1183 sf = &statfs; 1184 error = VFS_STATFS(vp->v_mount, sf); 1185 vput(vp); 1186 nfsm_reply(NFSX_STATFS); 1187 nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS); 1188 sfp->sf_tsize = txdr_unsigned(NFS_MAXDATA); 1189 sfp->sf_bsize = txdr_unsigned(sf->f_fsize); 1190 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 1191 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 1192 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 1193 nfsm_srvdone; 1194 } 1195 1196 /* 1197 * Null operation, used by clients to ping server 1198 */ 1199 nfsrv_null(mrep, md, dpos, cred, xid, mrq) 1200 struct mbuf **mrq; 1201 struct mbuf *mrep, *md; 1202 caddr_t dpos; 1203 struct ucred *cred; 1204 u_long xid; 1205 { 1206 nfsm_srvars; 1207 1208 error = VNOVAL; 1209 nfsm_reply(0); 1210 nfsm_srvdone; 1211 } 1212 1213 /* 1214 * No operation, used for obsolete procedures 1215 */ 1216 nfsrv_noop(mrep, md, dpos, cred, xid, mrq) 1217 struct mbuf **mrq; 1218 struct mbuf *mrep, *md; 1219 caddr_t dpos; 1220 struct ucred *cred; 1221 u_long xid; 1222 { 1223 nfsm_srvars; 1224 1225 error = EPROCUNAVAIL; 1226 nfsm_reply(0); 1227 nfsm_srvdone; 1228 } 1229 1230 /* 1231 * Perform access checking for vnodes obtained from file handles that would 1232 * refer to files already opened by a Unix client. You cannot just use 1233 * vn_writechk() and VOP_ACCESS() for two reasons. 1234 * 1 - You must check for M_EXRDONLY as well as M_RDONLY for the write case 1235 * 2 - The owner is to be given access irrespective of mode bits so that 1236 * processes that chmod after opening a file don't break. I don't like 1237 * this because it opens a security hole, but since the nfs server opens 1238 * a security hole the size of a barn door anyhow, what the heck. 1239 */ 1240 nfsrv_access(vp, flags, cred) 1241 register struct vnode *vp; 1242 int flags; 1243 register struct ucred *cred; 1244 { 1245 struct vattr vattr; 1246 int error; 1247 if (flags & VWRITE) { 1248 /* Just vn_writechk() changed to check M_EXRDONLY */ 1249 /* 1250 * Disallow write attempts on read-only file systems; 1251 * unless the file is a socket or a block or character 1252 * device resident on the file system. 1253 */ 1254 if ((vp->v_mount->m_flag & (M_RDONLY | M_EXRDONLY)) && 1255 vp->v_type != VCHR && 1256 vp->v_type != VBLK && 1257 vp->v_type != VSOCK) 1258 return (EROFS); 1259 /* 1260 * If there's shared text associated with 1261 * the inode, try to free it up once. If 1262 * we fail, we can't allow writing. 1263 */ 1264 if (vp->v_flag & VTEXT) 1265 xrele(vp); 1266 if (vp->v_flag & VTEXT) 1267 return (ETXTBSY); 1268 if (error = VOP_GETATTR(vp, &vattr, cred)) 1269 return (error); 1270 if (cred->cr_uid == vattr.va_uid) 1271 return (0); 1272 } else { 1273 if (error = VOP_GETATTR(vp, &vattr, cred)) 1274 return (error); 1275 if (cred->cr_uid == vattr.va_uid) 1276 return (0); 1277 } 1278 return (VOP_ACCESS(vp, flags, cred)); 1279 } 1280