1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 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 * @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 39 * $Id: vfs_vnops.c,v 1.7 1995/01/09 16:04:55 davidg Exp $ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/file.h> 46 #include <sys/stat.h> 47 #include <sys/buf.h> 48 #include <sys/proc.h> 49 #include <sys/mount.h> 50 #include <sys/namei.h> 51 #include <sys/vnode.h> 52 #include <sys/ioctl.h> 53 #include <sys/tty.h> 54 55 #include <vm/vm.h> 56 #include <vm/vnode_pager.h> 57 58 struct fileops vnops = 59 { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; 60 61 /* 62 * Common code for vnode open operations. 63 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 64 */ 65 int 66 vn_open(ndp, fmode, cmode) 67 register struct nameidata *ndp; 68 int fmode, cmode; 69 { 70 register struct vnode *vp; 71 register struct proc *p = ndp->ni_cnd.cn_proc; 72 register struct ucred *cred = p->p_ucred; 73 struct vattr vat; 74 struct vattr *vap = &vat; 75 int error; 76 77 if (fmode & O_CREAT) { 78 ndp->ni_cnd.cn_nameiop = CREATE; 79 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 80 if ((fmode & O_EXCL) == 0) 81 ndp->ni_cnd.cn_flags |= FOLLOW; 82 error = namei(ndp); 83 if (error) 84 return (error); 85 if (ndp->ni_vp == NULL) { 86 VATTR_NULL(vap); 87 vap->va_type = VREG; 88 vap->va_mode = cmode; 89 LEASE_CHECK(ndp->ni_dvp, p, cred, LEASE_WRITE); 90 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 91 &ndp->ni_cnd, vap); 92 if (error) 93 return (error); 94 fmode &= ~O_TRUNC; 95 vp = ndp->ni_vp; 96 } else { 97 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 98 if (ndp->ni_dvp == ndp->ni_vp) 99 vrele(ndp->ni_dvp); 100 else 101 vput(ndp->ni_dvp); 102 ndp->ni_dvp = NULL; 103 vp = ndp->ni_vp; 104 if (fmode & O_EXCL) { 105 error = EEXIST; 106 goto bad; 107 } 108 fmode &= ~O_CREAT; 109 } 110 } else { 111 ndp->ni_cnd.cn_nameiop = LOOKUP; 112 ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF; 113 error = namei(ndp); 114 if (error) 115 return (error); 116 vp = ndp->ni_vp; 117 } 118 if (vp->v_type == VSOCK) { 119 error = EOPNOTSUPP; 120 goto bad; 121 } 122 if ((fmode & O_CREAT) == 0) { 123 if (fmode & FREAD) { 124 error = VOP_ACCESS(vp, VREAD, cred, p); 125 if (error) 126 goto bad; 127 } 128 if (fmode & (FWRITE | O_TRUNC)) { 129 if (vp->v_type == VDIR) { 130 error = EISDIR; 131 goto bad; 132 } 133 error = vn_writechk(vp); 134 if(error) 135 goto bad; 136 error = VOP_ACCESS(vp, VWRITE, cred, p); 137 if(error) 138 goto bad; 139 } 140 } 141 if (fmode & O_TRUNC) { 142 VOP_UNLOCK(vp); /* XXX */ 143 LEASE_CHECK(vp, p, cred, LEASE_WRITE); 144 VOP_LOCK(vp); /* XXX */ 145 VATTR_NULL(vap); 146 vap->va_size = 0; 147 error = VOP_SETATTR(vp, vap, cred, p); 148 if (error) 149 goto bad; 150 } 151 error = VOP_OPEN(vp, fmode, cred, p); 152 if (error) 153 goto bad; 154 if (fmode & FWRITE) 155 vp->v_writecount++; 156 /* 157 * this is here for VMIO support 158 */ 159 if( vp->v_type == VREG) { 160 vm_object_t object; 161 vm_pager_t pager; 162 retry: 163 if( (vp->v_flag & VVMIO) == 0) { 164 pager = (vm_pager_t) vnode_pager_alloc( 165 (caddr_t) vp, 0, 0, 0); 166 object = (vm_object_t) vp->v_vmdata; 167 if( object->pager != pager) 168 panic("vn_open: pager/object mismatch"); 169 (void) vm_object_lookup( pager); 170 pager_cache( object, TRUE); 171 vp->v_flag |= VVMIO; 172 } else { 173 if( (object = (vm_object_t)vp->v_vmdata) && 174 (object->flags & OBJ_DEAD)) { 175 tsleep( (caddr_t) object, PVM, "vodead", 0); 176 goto retry; 177 } 178 if( !object) 179 panic("vn_open: VMIO object missing"); 180 pager = object->pager; 181 if( !pager) 182 panic("vn_open: VMIO pager missing"); 183 (void) vm_object_lookup( pager); 184 } 185 } 186 return (0); 187 bad: 188 vput(vp); 189 return (error); 190 } 191 192 /* 193 * Check for write permissions on the specified vnode. 194 * The read-only status of the file system is checked. 195 * Also, prototype text segments cannot be written. 196 */ 197 int 198 vn_writechk(vp) 199 register struct vnode *vp; 200 { 201 202 /* 203 * Disallow write attempts on read-only file systems; 204 * unless the file is a socket or a block or character 205 * device resident on the file system. 206 */ 207 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 208 switch (vp->v_type) { 209 case VREG: case VDIR: case VLNK: 210 return (EROFS); 211 default: 212 break; 213 } 214 } 215 /* 216 * If there's shared text associated with 217 * the vnode, try to free it up once. If 218 * we fail, we can't allow writing. 219 */ 220 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 221 return (ETXTBSY); 222 return (0); 223 } 224 225 /* 226 * Vnode close call 227 */ 228 int 229 vn_close(vp, flags, cred, p) 230 register struct vnode *vp; 231 int flags; 232 struct ucred *cred; 233 struct proc *p; 234 { 235 int error; 236 237 if (flags & FWRITE) 238 vp->v_writecount--; 239 error = VOP_CLOSE(vp, flags, cred, p); 240 /* 241 * this code is here for VMIO support, will eventually 242 * be in vfs code. 243 */ 244 if (vp->v_flag & VVMIO) { 245 vrele(vp); 246 if( vp->v_vmdata == NULL) 247 panic("vn_close: VMIO object missing"); 248 vm_object_deallocate( (vm_object_t) vp->v_vmdata); 249 } else 250 vrele(vp); 251 return (error); 252 } 253 254 /* 255 * Package up an I/O request on a vnode into a uio and do it. 256 */ 257 int 258 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) 259 enum uio_rw rw; 260 struct vnode *vp; 261 caddr_t base; 262 int len; 263 off_t offset; 264 enum uio_seg segflg; 265 int ioflg; 266 struct ucred *cred; 267 int *aresid; 268 struct proc *p; 269 { 270 struct uio auio; 271 struct iovec aiov; 272 int error; 273 274 if ((ioflg & IO_NODELOCKED) == 0) 275 VOP_LOCK(vp); 276 auio.uio_iov = &aiov; 277 auio.uio_iovcnt = 1; 278 aiov.iov_base = base; 279 aiov.iov_len = len; 280 auio.uio_resid = len; 281 auio.uio_offset = offset; 282 auio.uio_segflg = segflg; 283 auio.uio_rw = rw; 284 auio.uio_procp = p; 285 if (rw == UIO_READ) { 286 error = VOP_READ(vp, &auio, ioflg, cred); 287 } else { 288 error = VOP_WRITE(vp, &auio, ioflg, cred); 289 } 290 if (aresid) 291 *aresid = auio.uio_resid; 292 else 293 if (auio.uio_resid && error == 0) 294 error = EIO; 295 if ((ioflg & IO_NODELOCKED) == 0) 296 VOP_UNLOCK(vp); 297 return (error); 298 } 299 300 /* 301 * File table vnode read routine. 302 */ 303 int 304 vn_read(fp, uio, cred) 305 struct file *fp; 306 struct uio *uio; 307 struct ucred *cred; 308 { 309 register struct vnode *vp = (struct vnode *)fp->f_data; 310 int count, error; 311 312 LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_READ); 313 VOP_LOCK(vp); 314 uio->uio_offset = fp->f_offset; 315 count = uio->uio_resid; 316 error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, 317 cred); 318 fp->f_offset += count - uio->uio_resid; 319 VOP_UNLOCK(vp); 320 return (error); 321 } 322 323 /* 324 * File table vnode write routine. 325 */ 326 int 327 vn_write(fp, uio, cred) 328 struct file *fp; 329 struct uio *uio; 330 struct ucred *cred; 331 { 332 register struct vnode *vp = (struct vnode *)fp->f_data; 333 int count, error, ioflag = 0; 334 335 if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) 336 ioflag |= IO_APPEND; 337 if (fp->f_flag & FNONBLOCK) 338 ioflag |= IO_NDELAY; 339 LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_WRITE); 340 VOP_LOCK(vp); 341 uio->uio_offset = fp->f_offset; 342 count = uio->uio_resid; 343 error = VOP_WRITE(vp, uio, ioflag, cred); 344 if (ioflag & IO_APPEND) 345 fp->f_offset = uio->uio_offset; 346 else 347 fp->f_offset += count - uio->uio_resid; 348 VOP_UNLOCK(vp); 349 return (error); 350 } 351 352 /* 353 * File table vnode stat routine. 354 */ 355 int 356 vn_stat(vp, sb, p) 357 struct vnode *vp; 358 register struct stat *sb; 359 struct proc *p; 360 { 361 struct vattr vattr; 362 register struct vattr *vap; 363 int error; 364 u_short mode; 365 366 vap = &vattr; 367 error = VOP_GETATTR(vp, vap, p->p_ucred, p); 368 if (error) 369 return (error); 370 /* 371 * Copy from vattr table 372 */ 373 sb->st_dev = vap->va_fsid; 374 sb->st_ino = vap->va_fileid; 375 mode = vap->va_mode; 376 switch (vp->v_type) { 377 case VREG: 378 mode |= S_IFREG; 379 break; 380 case VDIR: 381 mode |= S_IFDIR; 382 break; 383 case VBLK: 384 mode |= S_IFBLK; 385 break; 386 case VCHR: 387 mode |= S_IFCHR; 388 break; 389 case VLNK: 390 mode |= S_IFLNK; 391 break; 392 case VSOCK: 393 mode |= S_IFSOCK; 394 break; 395 case VFIFO: 396 mode |= S_IFIFO; 397 break; 398 default: 399 return (EBADF); 400 }; 401 sb->st_mode = mode; 402 sb->st_nlink = vap->va_nlink; 403 sb->st_uid = vap->va_uid; 404 sb->st_gid = vap->va_gid; 405 sb->st_rdev = vap->va_rdev; 406 sb->st_size = vap->va_size; 407 sb->st_atimespec = vap->va_atime; 408 sb->st_mtimespec= vap->va_mtime; 409 sb->st_ctimespec = vap->va_ctime; 410 sb->st_blksize = vap->va_blocksize; 411 sb->st_flags = vap->va_flags; 412 sb->st_gen = vap->va_gen; 413 sb->st_blocks = vap->va_bytes / S_BLKSIZE; 414 return (0); 415 } 416 417 /* 418 * File table vnode ioctl routine. 419 */ 420 int 421 vn_ioctl(fp, com, data, p) 422 struct file *fp; 423 int com; 424 caddr_t data; 425 struct proc *p; 426 { 427 register struct vnode *vp = ((struct vnode *)fp->f_data); 428 struct vattr vattr; 429 int error; 430 431 switch (vp->v_type) { 432 433 case VREG: 434 case VDIR: 435 if (com == FIONREAD) { 436 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 437 if (error) 438 return (error); 439 *(int *)data = vattr.va_size - fp->f_offset; 440 return (0); 441 } 442 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 443 return (0); /* XXX */ 444 /* fall into ... */ 445 446 default: 447 return (ENOTTY); 448 449 case VFIFO: 450 case VCHR: 451 case VBLK: 452 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); 453 if (error == 0 && com == TIOCSCTTY) { 454 455 /* Do nothing if reassigning same control tty */ 456 if (p->p_session->s_ttyvp == vp) 457 return (0); 458 459 /* Get rid of reference to old control tty */ 460 if (p->p_session->s_ttyvp) 461 vrele(p->p_session->s_ttyvp); 462 463 p->p_session->s_ttyvp = vp; 464 VREF(vp); 465 } 466 return (error); 467 } 468 } 469 470 /* 471 * File table vnode select routine. 472 */ 473 int 474 vn_select(fp, which, p) 475 struct file *fp; 476 int which; 477 struct proc *p; 478 { 479 480 return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 481 fp->f_cred, p)); 482 } 483 484 /* 485 * File table vnode close routine. 486 */ 487 int 488 vn_closefile(fp, p) 489 struct file *fp; 490 struct proc *p; 491 { 492 493 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, 494 fp->f_cred, p)); 495 } 496