|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)vfs_vnops.c 7.33 (Berkeley) 6/27/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "kernel.h" ! 39: #include "file.h" ! 40: #include "stat.h" ! 41: #include "buf.h" ! 42: #include "proc.h" ! 43: #include "mount.h" ! 44: #include "namei.h" ! 45: #include "vnode.h" ! 46: #include "ioctl.h" ! 47: #include "tty.h" ! 48: ! 49: struct fileops vnops = ! 50: { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; ! 51: ! 52: /* ! 53: * Common code for vnode open operations. ! 54: * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. ! 55: */ ! 56: vn_open(ndp, p, fmode, cmode) ! 57: register struct nameidata *ndp; ! 58: struct proc *p; ! 59: int fmode, cmode; ! 60: { ! 61: register struct vnode *vp; ! 62: register struct ucred *cred = p->p_ucred; ! 63: struct vattr vat; ! 64: struct vattr *vap = &vat; ! 65: int error; ! 66: ! 67: if (fmode & O_CREAT) { ! 68: ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; ! 69: if ((fmode & O_EXCL) == 0) ! 70: ndp->ni_nameiop |= FOLLOW; ! 71: if (error = namei(ndp, p)) ! 72: return (error); ! 73: if (ndp->ni_vp == NULL) { ! 74: VATTR_NULL(vap); ! 75: vap->va_type = VREG; ! 76: vap->va_mode = cmode; ! 77: if (error = VOP_CREATE(ndp, vap, p)) ! 78: return (error); ! 79: fmode &= ~O_TRUNC; ! 80: vp = ndp->ni_vp; ! 81: } else { ! 82: VOP_ABORTOP(ndp); ! 83: if (ndp->ni_dvp == ndp->ni_vp) ! 84: vrele(ndp->ni_dvp); ! 85: else ! 86: vput(ndp->ni_dvp); ! 87: ndp->ni_dvp = NULL; ! 88: vp = ndp->ni_vp; ! 89: if (fmode & O_EXCL) { ! 90: error = EEXIST; ! 91: goto bad; ! 92: } ! 93: fmode &= ~O_CREAT; ! 94: } ! 95: } else { ! 96: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 97: if (error = namei(ndp, p)) ! 98: return (error); ! 99: vp = ndp->ni_vp; ! 100: } ! 101: if (vp->v_type == VSOCK) { ! 102: error = EOPNOTSUPP; ! 103: goto bad; ! 104: } ! 105: if ((fmode & O_CREAT) == 0) { ! 106: if (fmode & FREAD) { ! 107: if (error = VOP_ACCESS(vp, VREAD, cred, p)) ! 108: goto bad; ! 109: } ! 110: if (fmode & (FWRITE | O_TRUNC)) { ! 111: if (vp->v_type == VDIR) { ! 112: error = EISDIR; ! 113: goto bad; ! 114: } ! 115: if ((error = vn_writechk(vp)) || ! 116: (error = VOP_ACCESS(vp, VWRITE, cred, p))) ! 117: goto bad; ! 118: } ! 119: } ! 120: if (fmode & O_TRUNC) { ! 121: VATTR_NULL(vap); ! 122: vap->va_size = 0; ! 123: if (error = VOP_SETATTR(vp, vap, cred, p)) ! 124: goto bad; ! 125: } ! 126: if (error = VOP_OPEN(vp, fmode, cred, p)) ! 127: goto bad; ! 128: if (fmode & FWRITE) ! 129: vp->v_writecount++; ! 130: return (0); ! 131: bad: ! 132: vput(vp); ! 133: return (error); ! 134: } ! 135: ! 136: /* ! 137: * Check for write permissions on the specified vnode. ! 138: * The read-only status of the file system is checked. ! 139: * Also, prototype text segments cannot be written. ! 140: */ ! 141: vn_writechk(vp) ! 142: register struct vnode *vp; ! 143: { ! 144: ! 145: /* ! 146: * Disallow write attempts on read-only file systems; ! 147: * unless the file is a socket or a block or character ! 148: * device resident on the file system. ! 149: */ ! 150: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 151: switch (vp->v_type) { ! 152: case VREG: case VDIR: case VLNK: ! 153: return (EROFS); ! 154: } ! 155: } ! 156: /* ! 157: * If there's shared text associated with ! 158: * the vnode, try to free it up once. If ! 159: * we fail, we can't allow writing. ! 160: */ ! 161: if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) ! 162: return (ETXTBSY); ! 163: return (0); ! 164: } ! 165: ! 166: /* ! 167: * Vnode close call ! 168: */ ! 169: vn_close(vp, flags, cred, p) ! 170: register struct vnode *vp; ! 171: int flags; ! 172: struct ucred *cred; ! 173: struct proc *p; ! 174: { ! 175: int error; ! 176: ! 177: if (flags & FWRITE) ! 178: vp->v_writecount--; ! 179: error = VOP_CLOSE(vp, flags, cred, p); ! 180: vrele(vp); ! 181: return (error); ! 182: } ! 183: ! 184: /* ! 185: * Package up an I/O request on a vnode into a uio and do it. ! 186: */ ! 187: vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) ! 188: enum uio_rw rw; ! 189: struct vnode *vp; ! 190: caddr_t base; ! 191: int len; ! 192: off_t offset; ! 193: enum uio_seg segflg; ! 194: int ioflg; ! 195: struct ucred *cred; ! 196: int *aresid; ! 197: struct proc *p; ! 198: { ! 199: struct uio auio; ! 200: struct iovec aiov; ! 201: int error; ! 202: ! 203: if ((ioflg & IO_NODELOCKED) == 0) ! 204: VOP_LOCK(vp); ! 205: auio.uio_iov = &aiov; ! 206: auio.uio_iovcnt = 1; ! 207: aiov.iov_base = base; ! 208: aiov.iov_len = len; ! 209: auio.uio_resid = len; ! 210: auio.uio_offset = offset; ! 211: auio.uio_segflg = segflg; ! 212: auio.uio_rw = rw; ! 213: auio.uio_procp = p; ! 214: if (rw == UIO_READ) ! 215: error = VOP_READ(vp, &auio, ioflg, cred); ! 216: else ! 217: error = VOP_WRITE(vp, &auio, ioflg, cred); ! 218: if (aresid) ! 219: *aresid = auio.uio_resid; ! 220: else ! 221: if (auio.uio_resid && error == 0) ! 222: error = EIO; ! 223: if ((ioflg & IO_NODELOCKED) == 0) ! 224: VOP_UNLOCK(vp); ! 225: return (error); ! 226: } ! 227: ! 228: /* ! 229: * File table vnode read routine. ! 230: */ ! 231: vn_read(fp, uio, cred) ! 232: struct file *fp; ! 233: struct uio *uio; ! 234: struct ucred *cred; ! 235: { ! 236: register struct vnode *vp = (struct vnode *)fp->f_data; ! 237: int count, error; ! 238: ! 239: VOP_LOCK(vp); ! 240: uio->uio_offset = fp->f_offset; ! 241: count = uio->uio_resid; ! 242: error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, ! 243: cred); ! 244: fp->f_offset += count - uio->uio_resid; ! 245: VOP_UNLOCK(vp); ! 246: return (error); ! 247: } ! 248: ! 249: /* ! 250: * File table vnode write routine. ! 251: */ ! 252: vn_write(fp, uio, cred) ! 253: struct file *fp; ! 254: struct uio *uio; ! 255: struct ucred *cred; ! 256: { ! 257: register struct vnode *vp = (struct vnode *)fp->f_data; ! 258: int count, error, ioflag = 0; ! 259: ! 260: if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) ! 261: ioflag |= IO_APPEND; ! 262: if (fp->f_flag & FNONBLOCK) ! 263: ioflag |= IO_NDELAY; ! 264: VOP_LOCK(vp); ! 265: uio->uio_offset = fp->f_offset; ! 266: count = uio->uio_resid; ! 267: error = VOP_WRITE(vp, uio, ioflag, cred); ! 268: if (ioflag & IO_APPEND) ! 269: fp->f_offset = uio->uio_offset; ! 270: else ! 271: fp->f_offset += count - uio->uio_resid; ! 272: VOP_UNLOCK(vp); ! 273: return (error); ! 274: } ! 275: ! 276: /* ! 277: * File table vnode stat routine. ! 278: */ ! 279: vn_stat(vp, sb, p) ! 280: struct vnode *vp; ! 281: register struct stat *sb; ! 282: struct proc *p; ! 283: { ! 284: struct vattr vattr; ! 285: register struct vattr *vap; ! 286: int error; ! 287: u_short mode; ! 288: ! 289: vap = &vattr; ! 290: error = VOP_GETATTR(vp, vap, p->p_ucred, p); ! 291: if (error) ! 292: return (error); ! 293: /* ! 294: * Copy from vattr table ! 295: */ ! 296: sb->st_dev = vap->va_fsid; ! 297: sb->st_ino = vap->va_fileid; ! 298: mode = vap->va_mode; ! 299: switch (vp->v_type) { ! 300: case VREG: ! 301: mode |= S_IFREG; ! 302: break; ! 303: case VDIR: ! 304: mode |= S_IFDIR; ! 305: break; ! 306: case VBLK: ! 307: mode |= S_IFBLK; ! 308: break; ! 309: case VCHR: ! 310: mode |= S_IFCHR; ! 311: break; ! 312: case VLNK: ! 313: mode |= S_IFLNK; ! 314: break; ! 315: case VSOCK: ! 316: mode |= S_IFSOCK; ! 317: break; ! 318: case VFIFO: ! 319: mode |= S_IFIFO; ! 320: break; ! 321: default: ! 322: return (EBADF); ! 323: }; ! 324: sb->st_mode = mode; ! 325: sb->st_nlink = vap->va_nlink; ! 326: sb->st_uid = vap->va_uid; ! 327: sb->st_gid = vap->va_gid; ! 328: sb->st_rdev = vap->va_rdev; ! 329: sb->st_size = vap->va_size; ! 330: sb->st_atime = vap->va_atime.tv_sec; ! 331: sb->st_spare1 = 0; ! 332: sb->st_mtime = vap->va_mtime.tv_sec; ! 333: sb->st_spare2 = 0; ! 334: sb->st_ctime = vap->va_ctime.tv_sec; ! 335: sb->st_spare3 = 0; ! 336: sb->st_blksize = vap->va_blocksize; ! 337: sb->st_flags = vap->va_flags; ! 338: sb->st_gen = vap->va_gen; ! 339: sb->st_blocks = vap->va_bytes / S_BLKSIZE; ! 340: return (0); ! 341: } ! 342: ! 343: /* ! 344: * File table vnode ioctl routine. ! 345: */ ! 346: vn_ioctl(fp, com, data, p) ! 347: struct file *fp; ! 348: int com; ! 349: caddr_t data; ! 350: struct proc *p; ! 351: { ! 352: register struct vnode *vp = ((struct vnode *)fp->f_data); ! 353: struct vattr vattr; ! 354: int error; ! 355: ! 356: switch (vp->v_type) { ! 357: ! 358: case VREG: ! 359: case VDIR: ! 360: if (com == FIONREAD) { ! 361: if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) ! 362: return (error); ! 363: *(off_t *)data = vattr.va_size - fp->f_offset; ! 364: return (0); ! 365: } ! 366: if (com == FIONBIO || com == FIOASYNC) /* XXX */ ! 367: return (0); /* XXX */ ! 368: /* fall into ... */ ! 369: ! 370: default: ! 371: return (ENOTTY); ! 372: ! 373: case VFIFO: ! 374: case VCHR: ! 375: case VBLK: ! 376: error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); ! 377: if (error == 0 && com == TIOCSCTTY) { ! 378: p->p_session->s_ttyvp = vp; ! 379: VREF(vp); ! 380: } ! 381: return (error); ! 382: } ! 383: } ! 384: ! 385: /* ! 386: * File table vnode select routine. ! 387: */ ! 388: vn_select(fp, which, p) ! 389: struct file *fp; ! 390: int which; ! 391: struct proc *p; ! 392: { ! 393: ! 394: return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, ! 395: fp->f_cred, p)); ! 396: } ! 397: ! 398: /* ! 399: * File table vnode close routine. ! 400: */ ! 401: vn_closefile(fp, p) ! 402: struct file *fp; ! 403: struct proc *p; ! 404: { ! 405: ! 406: return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, ! 407: fp->f_cred, p)); ! 408: } ! 409: ! 410: /* ! 411: * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) ! 412: * - look up fsid in mount list (if not found ret error) ! 413: * - get vp by calling VFS_FHTOVP() macro ! 414: * - if lockflag lock it with VOP_LOCK() ! 415: */ ! 416: vn_fhtovp(fhp, lockflag, vpp) ! 417: fhandle_t *fhp; ! 418: int lockflag; ! 419: struct vnode **vpp; ! 420: { ! 421: register struct mount *mp; ! 422: ! 423: if ((mp = getvfs(&fhp->fh_fsid)) == NULL) ! 424: return (ESTALE); ! 425: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) ! 426: return (ESTALE); ! 427: if (!lockflag) ! 428: VOP_UNLOCK(*vpp); ! 429: return (0); ! 430: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.