123398Smckusick /* 237731Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337731Smckusick * All rights reserved. 423398Smckusick * 544460Sbostic * %sccs.include.redist.c% 637731Smckusick * 7*47540Skarels * @(#)vfs_vnops.c 7.27 (Berkeley) 03/17/91 823398Smckusick */ 918Sbill 1017099Sbloom #include "param.h" 1117099Sbloom #include "systm.h" 1217099Sbloom #include "user.h" 1337731Smckusick #include "kernel.h" 1417099Sbloom #include "file.h" 1537731Smckusick #include "stat.h" 1637731Smckusick #include "buf.h" 1737731Smckusick #include "proc.h" 1837731Smckusick #include "uio.h" 1917099Sbloom #include "socket.h" 2017099Sbloom #include "socketvar.h" 2137731Smckusick #include "mount.h" 2237731Smckusick #include "vnode.h" 2337731Smckusick #include "ioctl.h" 2437731Smckusick #include "tty.h" 2518Sbill 2637731Smckusick int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); 2737731Smckusick struct fileops vnops = 2837731Smckusick { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; 2937520Smckusick 3018Sbill /* 3137731Smckusick * Common code for vnode open operations. 3237731Smckusick * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 3318Sbill */ 34*47540Skarels vn_open(ndp, p, fmode, cmode) 3537731Smckusick register struct nameidata *ndp; 36*47540Skarels struct proc *p; 3737731Smckusick int fmode, cmode; 3837731Smckusick { 3937731Smckusick register struct vnode *vp; 40*47540Skarels register struct ucred *cred = p->p_ucred; 4137731Smckusick struct vattr vat; 4237731Smckusick struct vattr *vap = &vat; 4337731Smckusick int error; 4437731Smckusick 4537731Smckusick if (fmode & FCREAT) { 4637731Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 4737731Smckusick if ((fmode & FEXCL) == 0) 4837731Smckusick ndp->ni_nameiop |= FOLLOW; 49*47540Skarels if (error = namei(ndp, p)) 5037731Smckusick return (error); 5137731Smckusick if (ndp->ni_vp == NULL) { 5241362Smckusick VATTR_NULL(vap); 5337731Smckusick vap->va_type = VREG; 5437731Smckusick vap->va_mode = cmode; 5537731Smckusick if (error = VOP_CREATE(ndp, vap)) 5637731Smckusick return (error); 5737731Smckusick fmode &= ~FTRUNC; 5837731Smckusick vp = ndp->ni_vp; 5937731Smckusick } else { 6039761Smckusick if (ndp->ni_dvp == ndp->ni_vp) 6139761Smckusick vrele(ndp->ni_dvp); 6243343Smckusick else 6339761Smckusick vput(ndp->ni_dvp); 6439761Smckusick ndp->ni_dvp = NULL; 6537731Smckusick vp = ndp->ni_vp; 6637731Smckusick if (fmode & FEXCL) { 6737731Smckusick error = EEXIST; 6837731Smckusick goto bad; 6937731Smckusick } 7037731Smckusick fmode &= ~FCREAT; 7137731Smckusick } 7237731Smckusick } else { 7337731Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 74*47540Skarels if (error = namei(ndp, p)) 7537731Smckusick return (error); 7637731Smckusick vp = ndp->ni_vp; 7737731Smckusick } 7837731Smckusick if (vp->v_type == VSOCK) { 7937731Smckusick error = EOPNOTSUPP; 8037731Smckusick goto bad; 8137731Smckusick } 8237731Smckusick if ((fmode & FCREAT) == 0) { 8337731Smckusick if (fmode & FREAD) { 84*47540Skarels if (error = VOP_ACCESS(vp, VREAD, cred)) 8537731Smckusick goto bad; 8637731Smckusick } 8737731Smckusick if (fmode & (FWRITE|FTRUNC)) { 8837731Smckusick if (vp->v_type == VDIR) { 8937731Smckusick error = EISDIR; 9037731Smckusick goto bad; 9137731Smckusick } 9238401Smckusick if ((error = vn_writechk(vp)) || 93*47540Skarels (error = VOP_ACCESS(vp, VWRITE, cred))) 9438401Smckusick goto bad; 9537731Smckusick } 9637731Smckusick } 9737731Smckusick if (fmode & FTRUNC) { 9841362Smckusick VATTR_NULL(vap); 9937731Smckusick vap->va_size = 0; 100*47540Skarels if (error = VOP_SETATTR(vp, vap, cred)) 10137731Smckusick goto bad; 10237731Smckusick } 10337731Smckusick VOP_UNLOCK(vp); 104*47540Skarels error = VOP_OPEN(vp, fmode, cred); 10538351Smckusick if (error) 10638351Smckusick vrele(vp); 10738351Smckusick return (error); 10837731Smckusick 10937731Smckusick bad: 11037731Smckusick vput(vp); 11140707Skarels return (error); 11237731Smckusick } 11337731Smckusick 11437731Smckusick /* 11538401Smckusick * Check for write permissions on the specified vnode. 11638401Smckusick * The read-only status of the file system is checked. 11738401Smckusick * Also, prototype text segments cannot be written. 11837731Smckusick */ 11938401Smckusick vn_writechk(vp) 12037731Smckusick register struct vnode *vp; 12118Sbill { 12218Sbill 12338401Smckusick /* 12438401Smckusick * Disallow write attempts on read-only file systems; 12538401Smckusick * unless the file is a socket or a block or character 12638401Smckusick * device resident on the file system. 12738401Smckusick */ 12845060Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 12945060Smckusick switch (vp->v_type) { 13045060Smckusick case VREG: case VDIR: case VLNK: 13145060Smckusick return (EROFS); 13245060Smckusick } 13345060Smckusick } 13438401Smckusick /* 13538401Smckusick * If there's shared text associated with 13638401Smckusick * the vnode, try to free it up once. If 13738401Smckusick * we fail, we can't allow writing. 13838401Smckusick */ 13945744Smckusick if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 14038401Smckusick return (ETXTBSY); 14138401Smckusick return (0); 14237731Smckusick } 14337731Smckusick 14437731Smckusick /* 14537731Smckusick * Vnode version of rdwri() for calls on file systems. 14637731Smckusick */ 14737731Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 14837731Smckusick enum uio_rw rw; 14937731Smckusick struct vnode *vp; 15037731Smckusick caddr_t base; 15137731Smckusick int len; 15237731Smckusick off_t offset; 15337731Smckusick enum uio_seg segflg; 15437731Smckusick int ioflg; 15537731Smckusick struct ucred *cred; 15637731Smckusick int *aresid; 15737731Smckusick { 15837731Smckusick struct uio auio; 15937731Smckusick struct iovec aiov; 16037731Smckusick int error; 16137731Smckusick 16239590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 16339590Smckusick VOP_LOCK(vp); 16437731Smckusick auio.uio_iov = &aiov; 16537731Smckusick auio.uio_iovcnt = 1; 16637731Smckusick aiov.iov_base = base; 16737731Smckusick aiov.iov_len = len; 16837731Smckusick auio.uio_resid = len; 16937731Smckusick auio.uio_offset = offset; 17037731Smckusick auio.uio_segflg = segflg; 17137731Smckusick auio.uio_rw = rw; 17237731Smckusick if (rw == UIO_READ) 17339590Smckusick error = VOP_READ(vp, &auio, ioflg, cred); 17437731Smckusick else 17539590Smckusick error = VOP_WRITE(vp, &auio, ioflg, cred); 17637731Smckusick if (aresid) 17737731Smckusick *aresid = auio.uio_resid; 17837731Smckusick else 17937731Smckusick if (auio.uio_resid && error == 0) 18037731Smckusick error = EIO; 18139590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 18239590Smckusick VOP_UNLOCK(vp); 18337731Smckusick return (error); 18437731Smckusick } 18537731Smckusick 18637731Smckusick vn_read(fp, uio, cred) 18737731Smckusick struct file *fp; 18837731Smckusick struct uio *uio; 18937731Smckusick struct ucred *cred; 19037731Smckusick { 19139590Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 19239590Smckusick int count, error; 19337731Smckusick 19439590Smckusick VOP_LOCK(vp); 19539590Smckusick uio->uio_offset = fp->f_offset; 19639590Smckusick count = uio->uio_resid; 19739590Smckusick error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred); 19839590Smckusick fp->f_offset += count - uio->uio_resid; 19939590Smckusick VOP_UNLOCK(vp); 20039590Smckusick return (error); 20137731Smckusick } 20237731Smckusick 20337731Smckusick vn_write(fp, uio, cred) 20437731Smckusick struct file *fp; 20537731Smckusick struct uio *uio; 20637731Smckusick struct ucred *cred; 20737731Smckusick { 20837731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 20939590Smckusick int count, error, ioflag = 0; 21037731Smckusick 21137731Smckusick if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 21237731Smckusick ioflag |= IO_APPEND; 21337731Smckusick if (fp->f_flag & FNDELAY) 21437731Smckusick ioflag |= IO_NDELAY; 21539590Smckusick VOP_LOCK(vp); 21639590Smckusick uio->uio_offset = fp->f_offset; 21739590Smckusick count = uio->uio_resid; 21839590Smckusick error = VOP_WRITE(vp, uio, ioflag, cred); 21939590Smckusick if (ioflag & IO_APPEND) 22039590Smckusick fp->f_offset = uio->uio_offset; 22139590Smckusick else 22239590Smckusick fp->f_offset += count - uio->uio_resid; 22339590Smckusick VOP_UNLOCK(vp); 22439590Smckusick return (error); 22537731Smckusick } 22637731Smckusick 22737731Smckusick /* 22837731Smckusick * Get stat info for a vnode. 22937731Smckusick */ 23037731Smckusick vn_stat(vp, sb) 23137731Smckusick struct vnode *vp; 23237731Smckusick register struct stat *sb; 23337731Smckusick { 23437731Smckusick struct vattr vattr; 235*47540Skarels struct proc *p = curproc; /* XXX */ 23637731Smckusick register struct vattr *vap; 23737731Smckusick int error; 23837731Smckusick u_short mode; 23937731Smckusick 24037731Smckusick vap = &vattr; 241*47540Skarels error = VOP_GETATTR(vp, vap, p->p_ucred); 24237731Smckusick if (error) 24337731Smckusick return (error); 24437731Smckusick /* 24537731Smckusick * Copy from vattr table 24637731Smckusick */ 24737731Smckusick sb->st_dev = vap->va_fsid; 24837731Smckusick sb->st_ino = vap->va_fileid; 24937731Smckusick mode = vap->va_mode; 25037731Smckusick switch (vp->v_type) { 25137731Smckusick case VREG: 25239382Smckusick mode |= S_IFREG; 25337731Smckusick break; 25437731Smckusick case VDIR: 25539382Smckusick mode |= S_IFDIR; 25637731Smckusick break; 25737731Smckusick case VBLK: 25839382Smckusick mode |= S_IFBLK; 25937731Smckusick break; 26037731Smckusick case VCHR: 26139382Smckusick mode |= S_IFCHR; 26237731Smckusick break; 26337731Smckusick case VLNK: 26439382Smckusick mode |= S_IFLNK; 26537731Smckusick break; 26637731Smckusick case VSOCK: 26739382Smckusick mode |= S_IFSOCK; 26837731Smckusick break; 26940284Smckusick case VFIFO: 27040284Smckusick mode |= S_IFIFO; 27140284Smckusick break; 27237731Smckusick default: 27337731Smckusick return (EBADF); 27437731Smckusick }; 27537731Smckusick sb->st_mode = mode; 27637731Smckusick sb->st_nlink = vap->va_nlink; 27737731Smckusick sb->st_uid = vap->va_uid; 27837731Smckusick sb->st_gid = vap->va_gid; 27937731Smckusick sb->st_rdev = vap->va_rdev; 28037731Smckusick sb->st_size = vap->va_size; 28137731Smckusick sb->st_atime = vap->va_atime.tv_sec; 28237731Smckusick sb->st_spare1 = 0; 28337731Smckusick sb->st_mtime = vap->va_mtime.tv_sec; 28437731Smckusick sb->st_spare2 = 0; 28537731Smckusick sb->st_ctime = vap->va_ctime.tv_sec; 28637731Smckusick sb->st_spare3 = 0; 28737731Smckusick sb->st_blksize = vap->va_blocksize; 28838257Smckusick sb->st_flags = vap->va_flags; 28938257Smckusick sb->st_gen = vap->va_gen; 29038769Smckusick sb->st_blocks = vap->va_bytes / S_BLKSIZE; 29137731Smckusick return (0); 29237731Smckusick } 29337731Smckusick 29437731Smckusick /* 29537731Smckusick * Vnode ioctl call 29637731Smckusick */ 29737731Smckusick vn_ioctl(fp, com, data) 29837731Smckusick struct file *fp; 29937731Smckusick int com; 30037731Smckusick caddr_t data; 30137731Smckusick { 30237731Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 303*47540Skarels struct proc *p = curproc; /* XXX */ 30437731Smckusick struct vattr vattr; 30537731Smckusick int error; 30637731Smckusick 30737731Smckusick switch (vp->v_type) { 30837731Smckusick 30937731Smckusick case VREG: 31037731Smckusick case VDIR: 31137731Smckusick if (com == FIONREAD) { 312*47540Skarels if (error = VOP_GETATTR(vp, &vattr, p->p_ucred)) 31337731Smckusick return (error); 31437731Smckusick *(off_t *)data = vattr.va_size - fp->f_offset; 31537731Smckusick return (0); 31618Sbill } 31737731Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 31837731Smckusick return (0); /* XXX */ 31937731Smckusick /* fall into ... */ 32037731Smckusick 32137731Smckusick default: 32237731Smckusick return (ENOTTY); 32337731Smckusick 32440284Smckusick case VFIFO: 32537731Smckusick case VCHR: 32637731Smckusick case VBLK: 327*47540Skarels error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred); 32839564Smarc if (error == 0 && com == TIOCSCTTY) { 329*47540Skarels p->p_session->s_ttyvp = vp; 33039564Smarc VREF(vp); 33139564Smarc } 33239564Smarc return (error); 33318Sbill } 33437731Smckusick } 33537731Smckusick 33637731Smckusick /* 33737731Smckusick * Vnode select call 33837731Smckusick */ 33937731Smckusick vn_select(fp, which) 34037731Smckusick struct file *fp; 34137731Smckusick int which; 34237731Smckusick { 343*47540Skarels struct proc *p = curproc; /* XXX */ 344*47540Skarels 34540707Skarels return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 346*47540Skarels p->p_ucred)); 34737731Smckusick } 34837731Smckusick 34937731Smckusick /* 35037731Smckusick * Vnode close call 35137731Smckusick */ 35237731Smckusick vn_close(fp) 35337731Smckusick register struct file *fp; 35437731Smckusick { 35537731Smckusick struct vnode *vp = ((struct vnode *)fp->f_data); 35637731Smckusick int error; 35737731Smckusick 35811162Ssam /* 35937731Smckusick * Must delete vnode reference from this file entry 36037731Smckusick * before VOP_CLOSE, so that only other references 36137731Smckusick * will prevent close. 36211162Ssam */ 36337731Smckusick fp->f_data = (caddr_t) 0; 36446195Smckusick error = VOP_CLOSE(vp, fp->f_flag, fp->f_cred); 36537731Smckusick vrele(vp); 36637731Smckusick return (error); 36737731Smckusick } 36837731Smckusick 36937731Smckusick /* 37037731Smckusick * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 37137731Smckusick * - look up fsid in mount list (if not found ret error) 37237731Smckusick * - get vp by calling VFS_FHTOVP() macro 37337731Smckusick * - if lockflag lock it with VOP_LOCK() 37418Sbill */ 37537731Smckusick vn_fhtovp(fhp, lockflag, vpp) 37637731Smckusick fhandle_t *fhp; 37737731Smckusick int lockflag; 37837731Smckusick struct vnode **vpp; 37918Sbill { 38037731Smckusick register struct mount *mp; 38118Sbill 38237731Smckusick if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 38337731Smckusick return (ESTALE); 38438146Smckusick if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 38538146Smckusick return (ESTALE); 38638146Smckusick if (!lockflag) 38738146Smckusick VOP_UNLOCK(*vpp); 38837731Smckusick return (0); 38937731Smckusick } 390