123398Smckusick /* 263181Sbostic * Copyright (c) 1982, 1986, 1989, 1993 363181Sbostic * The Regents of the University of California. All rights reserved. 465771Sbostic * (c) UNIX System Laboratories, Inc. 565771Sbostic * All or some portions of this file are derived from material licensed 665771Sbostic * to the University of California by American Telephone and Telegraph 765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 865771Sbostic * the permission of UNIX System Laboratories, Inc. 923398Smckusick * 1044460Sbostic * %sccs.include.redist.c% 1137731Smckusick * 12*68712Smckusick * @(#)vfs_vnops.c 8.9 (Berkeley) 04/02/95 1323398Smckusick */ 1418Sbill 1556517Sbostic #include <sys/param.h> 1656517Sbostic #include <sys/systm.h> 1756517Sbostic #include <sys/kernel.h> 1856517Sbostic #include <sys/file.h> 1956517Sbostic #include <sys/stat.h> 2056517Sbostic #include <sys/buf.h> 2156517Sbostic #include <sys/proc.h> 2256517Sbostic #include <sys/mount.h> 2356517Sbostic #include <sys/namei.h> 2456517Sbostic #include <sys/vnode.h> 2556517Sbostic #include <sys/ioctl.h> 2656517Sbostic #include <sys/tty.h> 2756517Sbostic 2853469Smckusick #include <vm/vm.h> 2918Sbill 3037731Smckusick struct fileops vnops = 3150164Smckusick { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; 3237520Smckusick 3318Sbill /* 3437731Smckusick * Common code for vnode open operations. 3537731Smckusick * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 3618Sbill */ 3752310Smckusick vn_open(ndp, fmode, cmode) 3837731Smckusick register struct nameidata *ndp; 3937731Smckusick int fmode, cmode; 4037731Smckusick { 4137731Smckusick register struct vnode *vp; 4252310Smckusick register struct proc *p = ndp->ni_cnd.cn_proc; 4352331Smckusick register struct ucred *cred = p->p_ucred; 4437731Smckusick struct vattr vat; 4537731Smckusick struct vattr *vap = &vat; 4637731Smckusick int error; 4737731Smckusick 4849943Smckusick if (fmode & O_CREAT) { 4952310Smckusick ndp->ni_cnd.cn_nameiop = CREATE; 5052310Smckusick ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 5149943Smckusick if ((fmode & O_EXCL) == 0) 5252310Smckusick ndp->ni_cnd.cn_flags |= FOLLOW; 5352310Smckusick if (error = namei(ndp)) 5437731Smckusick return (error); 5537731Smckusick if (ndp->ni_vp == NULL) { 5641362Smckusick VATTR_NULL(vap); 5737731Smckusick vap->va_type = VREG; 5837731Smckusick vap->va_mode = cmode; 5968578Smckusick if (fmode & O_EXCL) 6068578Smckusick vap->va_vaflags |= VA_EXCLUSIVE; 6167655Smckusick VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE); 6252310Smckusick if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 6352310Smckusick &ndp->ni_cnd, vap)) 6437731Smckusick return (error); 6549943Smckusick fmode &= ~O_TRUNC; 6637731Smckusick vp = ndp->ni_vp; 6737731Smckusick } else { 6852230Sheideman VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 6939761Smckusick if (ndp->ni_dvp == ndp->ni_vp) 7039761Smckusick vrele(ndp->ni_dvp); 7143343Smckusick else 7239761Smckusick vput(ndp->ni_dvp); 7339761Smckusick ndp->ni_dvp = NULL; 7437731Smckusick vp = ndp->ni_vp; 7549943Smckusick if (fmode & O_EXCL) { 7637731Smckusick error = EEXIST; 7737731Smckusick goto bad; 7837731Smckusick } 7949943Smckusick fmode &= ~O_CREAT; 8037731Smckusick } 8137731Smckusick } else { 8252310Smckusick ndp->ni_cnd.cn_nameiop = LOOKUP; 8352310Smckusick ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF; 8452310Smckusick if (error = namei(ndp)) 8537731Smckusick return (error); 8637731Smckusick vp = ndp->ni_vp; 8737731Smckusick } 8837731Smckusick if (vp->v_type == VSOCK) { 8937731Smckusick error = EOPNOTSUPP; 9037731Smckusick goto bad; 9137731Smckusick } 9249943Smckusick if ((fmode & O_CREAT) == 0) { 9337731Smckusick if (fmode & FREAD) { 9448030Smckusick if (error = VOP_ACCESS(vp, VREAD, cred, p)) 9537731Smckusick goto bad; 9637731Smckusick } 9749943Smckusick if (fmode & (FWRITE | O_TRUNC)) { 9837731Smckusick if (vp->v_type == VDIR) { 9937731Smckusick error = EISDIR; 10037731Smckusick goto bad; 10137731Smckusick } 10238401Smckusick if ((error = vn_writechk(vp)) || 10348030Smckusick (error = VOP_ACCESS(vp, VWRITE, cred, p))) 10438401Smckusick goto bad; 10537731Smckusick } 10637731Smckusick } 10749943Smckusick if (fmode & O_TRUNC) { 10859381Smckusick VOP_UNLOCK(vp); /* XXX */ 10967655Smckusick VOP_LEASE(vp, p, cred, LEASE_WRITE); 11059381Smckusick VOP_LOCK(vp); /* XXX */ 11141362Smckusick VATTR_NULL(vap); 11237731Smckusick vap->va_size = 0; 11348030Smckusick if (error = VOP_SETATTR(vp, vap, cred, p)) 11437731Smckusick goto bad; 11537731Smckusick } 11650110Smckusick if (error = VOP_OPEN(vp, fmode, cred, p)) 11750110Smckusick goto bad; 11850110Smckusick if (fmode & FWRITE) 11950110Smckusick vp->v_writecount++; 12050110Smckusick return (0); 12137731Smckusick bad: 12237731Smckusick vput(vp); 12340707Skarels return (error); 12437731Smckusick } 12537731Smckusick 12637731Smckusick /* 12738401Smckusick * Check for write permissions on the specified vnode. 12838401Smckusick * The read-only status of the file system is checked. 12938401Smckusick * Also, prototype text segments cannot be written. 13037731Smckusick */ 13138401Smckusick vn_writechk(vp) 13237731Smckusick register struct vnode *vp; 13318Sbill { 13418Sbill 13538401Smckusick /* 13638401Smckusick * Disallow write attempts on read-only file systems; 13738401Smckusick * unless the file is a socket or a block or character 13838401Smckusick * device resident on the file system. 13938401Smckusick */ 14045060Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 14145060Smckusick switch (vp->v_type) { 14245060Smckusick case VREG: case VDIR: case VLNK: 14345060Smckusick return (EROFS); 14445060Smckusick } 14545060Smckusick } 14638401Smckusick /* 14738401Smckusick * If there's shared text associated with 14838401Smckusick * the vnode, try to free it up once. If 14938401Smckusick * we fail, we can't allow writing. 15038401Smckusick */ 15145744Smckusick if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 15238401Smckusick return (ETXTBSY); 15338401Smckusick return (0); 15437731Smckusick } 15537731Smckusick 15637731Smckusick /* 15750164Smckusick * Vnode close call 15837731Smckusick */ 15950164Smckusick vn_close(vp, flags, cred, p) 16050164Smckusick register struct vnode *vp; 16150164Smckusick int flags; 16250164Smckusick struct ucred *cred; 16350164Smckusick struct proc *p; 16450164Smckusick { 16550164Smckusick int error; 16650164Smckusick 16750164Smckusick if (flags & FWRITE) 16850164Smckusick vp->v_writecount--; 16950164Smckusick error = VOP_CLOSE(vp, flags, cred, p); 17050164Smckusick vrele(vp); 17150164Smckusick return (error); 17250164Smckusick } 17350164Smckusick 17450164Smckusick /* 17550164Smckusick * Package up an I/O request on a vnode into a uio and do it. 17650164Smckusick */ 17748030Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) 17837731Smckusick enum uio_rw rw; 17937731Smckusick struct vnode *vp; 18037731Smckusick caddr_t base; 18137731Smckusick int len; 18237731Smckusick off_t offset; 18337731Smckusick enum uio_seg segflg; 18437731Smckusick int ioflg; 18537731Smckusick struct ucred *cred; 18637731Smckusick int *aresid; 18748030Smckusick struct proc *p; 18837731Smckusick { 18937731Smckusick struct uio auio; 19037731Smckusick struct iovec aiov; 19137731Smckusick int error; 19237731Smckusick 19339590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 19439590Smckusick VOP_LOCK(vp); 19537731Smckusick auio.uio_iov = &aiov; 19637731Smckusick auio.uio_iovcnt = 1; 19737731Smckusick aiov.iov_base = base; 19837731Smckusick aiov.iov_len = len; 19937731Smckusick auio.uio_resid = len; 20037731Smckusick auio.uio_offset = offset; 20137731Smckusick auio.uio_segflg = segflg; 20237731Smckusick auio.uio_rw = rw; 20348030Smckusick auio.uio_procp = p; 20452191Smckusick if (rw == UIO_READ) { 20539590Smckusick error = VOP_READ(vp, &auio, ioflg, cred); 20652191Smckusick } else { 20739590Smckusick error = VOP_WRITE(vp, &auio, ioflg, cred); 20852191Smckusick } 20937731Smckusick if (aresid) 21037731Smckusick *aresid = auio.uio_resid; 21137731Smckusick else 21237731Smckusick if (auio.uio_resid && error == 0) 21337731Smckusick error = EIO; 21439590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 21539590Smckusick VOP_UNLOCK(vp); 21637731Smckusick return (error); 21737731Smckusick } 21837731Smckusick 21950164Smckusick /* 22050164Smckusick * File table vnode read routine. 22150164Smckusick */ 22237731Smckusick vn_read(fp, uio, cred) 22337731Smckusick struct file *fp; 22437731Smckusick struct uio *uio; 22537731Smckusick struct ucred *cred; 22637731Smckusick { 22739590Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 22839590Smckusick int count, error; 22937731Smckusick 23067655Smckusick VOP_LEASE(vp, uio->uio_procp, cred, LEASE_READ); 23139590Smckusick VOP_LOCK(vp); 23239590Smckusick uio->uio_offset = fp->f_offset; 23339590Smckusick count = uio->uio_resid; 23449943Smckusick error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, 23549943Smckusick cred); 23639590Smckusick fp->f_offset += count - uio->uio_resid; 23739590Smckusick VOP_UNLOCK(vp); 23839590Smckusick return (error); 23937731Smckusick } 24037731Smckusick 24150164Smckusick /* 24250164Smckusick * File table vnode write routine. 24350164Smckusick */ 24437731Smckusick vn_write(fp, uio, cred) 24537731Smckusick struct file *fp; 24637731Smckusick struct uio *uio; 24737731Smckusick struct ucred *cred; 24837731Smckusick { 24937731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 25068064Smckusick int count, error, ioflag = IO_UNIT; 25137731Smckusick 25249943Smckusick if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) 25337731Smckusick ioflag |= IO_APPEND; 25449943Smckusick if (fp->f_flag & FNONBLOCK) 25537731Smckusick ioflag |= IO_NDELAY; 256*68712Smckusick if (fp->f_flag & O_FSYNC) 257*68712Smckusick ioflag |= IO_SYNC; 25867655Smckusick VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE); 25939590Smckusick VOP_LOCK(vp); 26039590Smckusick uio->uio_offset = fp->f_offset; 26139590Smckusick count = uio->uio_resid; 26239590Smckusick error = VOP_WRITE(vp, uio, ioflag, cred); 26339590Smckusick if (ioflag & IO_APPEND) 26439590Smckusick fp->f_offset = uio->uio_offset; 26539590Smckusick else 26639590Smckusick fp->f_offset += count - uio->uio_resid; 26739590Smckusick VOP_UNLOCK(vp); 26839590Smckusick return (error); 26937731Smckusick } 27037731Smckusick 27137731Smckusick /* 27250164Smckusick * File table vnode stat routine. 27337731Smckusick */ 27448030Smckusick vn_stat(vp, sb, p) 27537731Smckusick struct vnode *vp; 27637731Smckusick register struct stat *sb; 27748030Smckusick struct proc *p; 27837731Smckusick { 27937731Smckusick struct vattr vattr; 28037731Smckusick register struct vattr *vap; 28137731Smckusick int error; 28237731Smckusick u_short mode; 28337731Smckusick 28437731Smckusick vap = &vattr; 28548030Smckusick error = VOP_GETATTR(vp, vap, p->p_ucred, p); 28637731Smckusick if (error) 28737731Smckusick return (error); 28837731Smckusick /* 28937731Smckusick * Copy from vattr table 29037731Smckusick */ 29137731Smckusick sb->st_dev = vap->va_fsid; 29237731Smckusick sb->st_ino = vap->va_fileid; 29337731Smckusick mode = vap->va_mode; 29437731Smckusick switch (vp->v_type) { 29537731Smckusick case VREG: 29639382Smckusick mode |= S_IFREG; 29737731Smckusick break; 29837731Smckusick case VDIR: 29939382Smckusick mode |= S_IFDIR; 30037731Smckusick break; 30137731Smckusick case VBLK: 30239382Smckusick mode |= S_IFBLK; 30337731Smckusick break; 30437731Smckusick case VCHR: 30539382Smckusick mode |= S_IFCHR; 30637731Smckusick break; 30737731Smckusick case VLNK: 30839382Smckusick mode |= S_IFLNK; 30937731Smckusick break; 31037731Smckusick case VSOCK: 31139382Smckusick mode |= S_IFSOCK; 31237731Smckusick break; 31340284Smckusick case VFIFO: 31440284Smckusick mode |= S_IFIFO; 31540284Smckusick break; 31637731Smckusick default: 31737731Smckusick return (EBADF); 31837731Smckusick }; 31937731Smckusick sb->st_mode = mode; 32037731Smckusick sb->st_nlink = vap->va_nlink; 32137731Smckusick sb->st_uid = vap->va_uid; 32237731Smckusick sb->st_gid = vap->va_gid; 32337731Smckusick sb->st_rdev = vap->va_rdev; 32437731Smckusick sb->st_size = vap->va_size; 32554100Smckusick sb->st_atimespec = vap->va_atime; 32668321Scgd sb->st_mtimespec = vap->va_mtime; 32754100Smckusick sb->st_ctimespec = vap->va_ctime; 32837731Smckusick sb->st_blksize = vap->va_blocksize; 32938257Smckusick sb->st_flags = vap->va_flags; 33038257Smckusick sb->st_gen = vap->va_gen; 33138769Smckusick sb->st_blocks = vap->va_bytes / S_BLKSIZE; 33237731Smckusick return (0); 33337731Smckusick } 33437731Smckusick 33537731Smckusick /* 33650164Smckusick * File table vnode ioctl routine. 33737731Smckusick */ 33848030Smckusick vn_ioctl(fp, com, data, p) 33937731Smckusick struct file *fp; 34068171Scgd u_long com; 34137731Smckusick caddr_t data; 34248030Smckusick struct proc *p; 34337731Smckusick { 34437731Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 34537731Smckusick struct vattr vattr; 34637731Smckusick int error; 34737731Smckusick 34837731Smckusick switch (vp->v_type) { 34937731Smckusick 35037731Smckusick case VREG: 35137731Smckusick case VDIR: 35237731Smckusick if (com == FIONREAD) { 35348030Smckusick if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 35437731Smckusick return (error); 35554772Storek *(int *)data = vattr.va_size - fp->f_offset; 35637731Smckusick return (0); 35718Sbill } 35837731Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 35937731Smckusick return (0); /* XXX */ 36037731Smckusick /* fall into ... */ 36137731Smckusick 36237731Smckusick default: 36337731Smckusick return (ENOTTY); 36437731Smckusick 36540284Smckusick case VFIFO: 36637731Smckusick case VCHR: 36737731Smckusick case VBLK: 36848030Smckusick error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); 36939564Smarc if (error == 0 && com == TIOCSCTTY) { 37067686Smckusick if (p->p_session->s_ttyvp) 37167686Smckusick vrele(p->p_session->s_ttyvp); 37247540Skarels p->p_session->s_ttyvp = vp; 37339564Smarc VREF(vp); 37439564Smarc } 37539564Smarc return (error); 37618Sbill } 37737731Smckusick } 37837731Smckusick 37937731Smckusick /* 38050164Smckusick * File table vnode select routine. 38137731Smckusick */ 38248030Smckusick vn_select(fp, which, p) 38337731Smckusick struct file *fp; 38437731Smckusick int which; 38548030Smckusick struct proc *p; 38637731Smckusick { 38747540Skarels 38840707Skarels return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 38950164Smckusick fp->f_cred, p)); 39037731Smckusick } 39137731Smckusick 39237731Smckusick /* 39350164Smckusick * File table vnode close routine. 39437731Smckusick */ 39550164Smckusick vn_closefile(fp, p) 39650164Smckusick struct file *fp; 39748030Smckusick struct proc *p; 39837731Smckusick { 39937731Smckusick 40050164Smckusick return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, 40150164Smckusick fp->f_cred, p)); 40237731Smckusick } 403