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.14.4 (2.11BSD) 1999/9/13 39: */ 40: 41: #include <sys/param.h> 42: #include <sys/file.h> 43: #include <sys/user.h> 44: #include <sys/namei.h> 45: #include <sys/inode.h> 46: #include <sys/stat.h> 47: 48: /* 49: * 2.11BSD does not have "vnodes", having instead only old fashioned "inodes". 50: * The routine names (i.e. vn_open) were retained since the functions them- 51: * selves were ported over with minimal change. Retaining the 4.4 function 52: * names also makes it easier to follow the logic flow when reading the 4.4 53: * sources. Also, changing the names from vn_* to in_* could have caused 54: * confusion with the networking routines since 'in_' and 'ip_' are frequently 55: * used in the networking code. 56: * 57: * The tab spacing has been altered to be (to me) more readable. 58: */ 59: 60: /* 61: * Common code for vnode open operations. 62: * Check permissions, and call the VOP_OPEN (openi for 2.11) or VOP_CREATE 63: * (maknode) routine. 64: */ 65: vn_open(ndp, fmode, cmode) 66: register struct nameidata *ndp; 67: int fmode, cmode; 68: { 69: register struct inode *ip; 70: register int error; 71: 72: if (fmode & O_CREAT) 73: { 74: if ((fmode & O_EXCL) == 0) 75: ndp->ni_nameiop |= (CREATE|FOLLOW); 76: else 77: ndp->ni_nameiop= CREATE; 78: ip = namei(ndp); 79: if (ip == NULL) 80: { 81: if (u.u_error) 82: goto retuerr; 83: ip = maknode(cmode, ndp); 84: if (ip == NULL) 85: goto retuerr; 86: fmode &= ~O_TRUNC; 87: } 88: else 89: { 90: if (fmode & O_EXCL) 91: { 92: error = EEXIST; 93: goto bad; 94: } 95: fmode &= ~O_CREAT; 96: } 97: } 98: else 99: { 100: ndp->ni_nameiop = LOOKUP | FOLLOW; 101: ip = namei(ndp); 102: if (ip == NULL) 103: goto retuerr; 104: } 105: if ((ip->i_mode & IFMT) == IFSOCK) 106: { 107: error = EOPNOTSUPP; 108: goto bad; 109: } 110: if ((ip->i_flags & APPEND) && (fmode&(FWRITE|O_APPEND)) == FWRITE) 111: { 112: error = EPERM; 113: goto bad; 114: } 115: if ((fmode & O_CREAT) == 0) 116: { 117: if (fmode & FREAD) 118: { 119: if (access(ip, IREAD)) 120: { 121: error = u.u_error; /* XXX */ 122: goto bad; 123: } 124: } 125: if (fmode & (FWRITE | O_TRUNC)) 126: { 127: if ((ip->i_mode & IFMT) == IFDIR) 128: { 129: error = EISDIR; 130: goto bad; 131: } 132: if (access(ip, IWRITE)) 133: { 134: error = u.u_error; 135: goto bad; 136: } 137: } 138: } 139: if (fmode & O_TRUNC) 140: itrunc(ip, (off_t)0, fmode & O_FSYNC ? IO_SYNC : 0); 141: /* 142: * 4.4 returns the vnode locked from vn_open which means that each caller 143: * has to go and unlock it. 144: * 145: * 2.11 returns the inode unlocked (for now). 146: */ 147: iunlock(ip); /* because namei returns a locked inode */ 148: if (setjmp(&u.u_qsave)) 149: { 150: error = EINTR; /* opens are not restarted after signals */ 151: goto lbad; 152: } 153: if (error = openi(ip, fmode)) 154: goto lbad; 155: return(0); 156: /* 157: * Gratuitous lock but it does (correctly) implement the earlier behaviour of 158: * copen (it also avoids a panic in iput). 159: */ 160: 161: lbad: 162: ilock(ip); 163: 164: bad: 165: /* 166: * Do NOT do an 'ilock' here - this tag is to be used only when the inode is 167: * locked (i.e. from namei). 168: */ 169: iput(ip); 170: return(error); 171: retuerr: 172: return(u.u_error); /* XXX - Bletch */ 173: } 174: 175: /* 176: * Inode close call. Pipes and sockets do NOT enter here. This routine is 177: * used by the kernel to close files it opened for itself (see kern_acct.c 178: * for a good example of this). The kernel does not create sockets or pipes 179: * on its own behalf. 180: * 181: * The difference between this routine and vn_closefile below is that vn_close 182: * takes an "inode *" as a first argument and is passed the flags by the caller 183: * while vn_closefile (called from the closef routine for DTYPE_INODE inodes) 184: * takes a "file *" and extracts the flags from the file structure. 185: */ 186: vn_close(ip, flags) 187: register struct inode *ip; 188: int flags; 189: { 190: register int error; 191: 192: error = closei(ip, flags); 193: irele(ip); /* assumes inode is unlocked */ 194: return(error); 195: } 196: 197: /* 198: * File table inode close routine. This is called from 'closef()' via the 199: * "Fops" table (the 'inodeops' entry). 200: * 201: * NOTE: pipes are a special case of inode and have their own 'pipe_close' 202: * entry in the 'pipeops' table. See sys_pipe.c for pipe_close(). 203: * 204: * In 4.4BSD this routine called vn_close() but since 2.11 does not do the 205: * writecheck counting we can skip the overhead of nesting another level down 206: * and call closei() and irele() ourself. 207: */ 208: vn_closefile(fp) 209: register struct file *fp; 210: { 211: register struct inode *ip = (struct inode *)fp->f_data; 212: 213: /* 214: * Need to clear the inode pointer in the file structure so that the 215: * inode is not seen during the scan for aliases of character or block 216: * devices in closei(). 217: */ 218: fp->f_data = (caddr_t)0; /* XXX */ 219: irele(ip); 220: return(closei(ip, fp->f_flag)); 221: }