1 /* vfs_vnops.c 4.19 82/01/19 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/filsys.h" 8 #include "../h/file.h" 9 #include "../h/conf.h" 10 #include "../h/inode.h" 11 #include "../h/reg.h" 12 #include "../h/acct.h" 13 #include "../h/mount.h" 14 #include "../h/socket.h" 15 #include "../h/socketvar.h" 16 #include "../h/proc.h" 17 18 /* 19 * Convert a user supplied file descriptor into a pointer 20 * to a file structure. Only task is to check range of the descriptor. 21 * Critical paths should use the GETF macro, defined in inline.h. 22 */ 23 struct file * 24 getf(f) 25 register int f; 26 { 27 register struct file *fp; 28 29 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 30 u.u_error = EBADF; 31 return (NULL); 32 } 33 return (fp); 34 } 35 36 /* 37 * Internal form of close. 38 * Decrement reference count on 39 * file structure. 40 * Also make sure the pipe protocol 41 * does not constipate. 42 * 43 * Decrement reference count on the inode following 44 * removal to the referencing file structure. 45 * Call device handler on last close. 46 * Nouser indicates that the user isn't available to present 47 * errors to. 48 */ 49 closef(fp, nouser) 50 register struct file *fp; 51 { 52 register struct inode *ip; 53 register struct mount *mp; 54 int flag, mode; 55 dev_t dev; 56 register int (*cfunc)(); 57 58 if (fp == NULL) 59 return; 60 if (fp->f_count > 1) { 61 fp->f_count--; 62 return; 63 } 64 flag = fp->f_flag; 65 if (flag & FSOCKET) { 66 soclose(fp->f_socket, nouser); 67 if (u.u_error) 68 return; 69 fp->f_socket = 0; 70 fp->f_count = 0; 71 return; 72 } 73 ip = fp->f_inode; 74 dev = (dev_t)ip->i_un.i_rdev; 75 mode = ip->i_mode & IFMT; 76 ilock(ip); 77 iput(ip); 78 fp->f_count = 0; 79 80 switch (mode) { 81 82 case IFCHR: 83 cfunc = cdevsw[major(dev)].d_close; 84 break; 85 86 case IFBLK: 87 /* 88 * We don't want to really close the device if it is mounted 89 */ 90 for (mp = mount; mp < &mount[NMOUNT]; mp++) 91 if (mp->m_bufp != NULL && mp->m_dev == dev) 92 return; 93 cfunc = bdevsw[major(dev)].d_close; 94 break; 95 96 default: 97 return; 98 } 99 for (fp = file; fp < fileNFILE; fp++) { 100 if (fp->f_flag & FSOCKET) 101 continue; 102 if (fp->f_count && (ip = fp->f_inode) && 103 ip->i_un.i_rdev == dev && (ip->i_mode&IFMT) == mode) 104 return; 105 } 106 if (mode == IFBLK) { 107 /* 108 * On last close of a block device (that isn't mounted) 109 * we must invalidate any in core blocks 110 */ 111 bflush(dev); 112 binval(dev); 113 } 114 (*cfunc)(dev, flag, fp); 115 } 116 117 /* 118 * Openi called to allow handler 119 * of special files to initialize and 120 * validate before actual IO. 121 */ 122 openi(ip, rw) 123 register struct inode *ip; 124 { 125 dev_t dev; 126 register unsigned int maj; 127 128 dev = (dev_t)ip->i_un.i_rdev; 129 maj = major(dev); 130 switch (ip->i_mode&IFMT) { 131 132 case IFCHR: 133 if (maj >= nchrdev) 134 goto bad; 135 (*cdevsw[maj].d_open)(dev, rw); 136 break; 137 138 case IFBLK: 139 if (maj >= nblkdev) 140 goto bad; 141 (*bdevsw[maj].d_open)(dev, rw); 142 } 143 return; 144 145 bad: 146 u.u_error = ENXIO; 147 } 148 149 /* 150 * Check mode permission on inode pointer. 151 * Mode is READ, WRITE or EXEC. 152 * In the case of WRITE, the 153 * read-only status of the file 154 * system is checked. 155 * Also in WRITE, prototype text 156 * segments cannot be written. 157 * The mode is shifted to select 158 * the owner/group/other fields. 159 * The super user is granted all 160 * permissions. 161 */ 162 access(ip, mode) 163 register struct inode *ip; 164 int mode; 165 { 166 register m; 167 168 m = mode; 169 if (m == IWRITE) { 170 if (getfs(ip->i_dev)->s_ronly != 0) { 171 u.u_error = EROFS; 172 return (1); 173 } 174 if (ip->i_flag&ITEXT) /* try to free text */ 175 xrele(ip); 176 if (ip->i_flag & ITEXT) { 177 u.u_error = ETXTBSY; 178 return (1); 179 } 180 } 181 if (u.u_uid == 0) 182 return (0); 183 if (u.u_uid != ip->i_uid) { 184 m >>= 3; 185 if (u.u_gid != ip->i_gid) 186 m >>= 3; 187 } 188 if ((ip->i_mode&m) != 0) 189 return (0); 190 u.u_error = EACCES; 191 return (1); 192 } 193 194 /* 195 * Look up a pathname and test if 196 * the resultant inode is owned by the 197 * current user. 198 * If not, try for super-user. 199 * If permission is granted, 200 * return inode pointer. 201 */ 202 struct inode * 203 owner() 204 { 205 register struct inode *ip; 206 207 ip = namei(uchar, 0); 208 if (ip == NULL) 209 return (NULL); 210 if (u.u_uid == ip->i_uid) 211 return (ip); 212 if (suser()) 213 return (ip); 214 iput(ip); 215 return (NULL); 216 } 217 218 /* 219 * Test if the current user is the 220 * super user. 221 */ 222 suser() 223 { 224 225 if (u.u_uid == 0) { 226 u.u_acflag |= ASU; 227 return (1); 228 } 229 u.u_error = EPERM; 230 return (0); 231 } 232 233 /* 234 * Allocate a user file descriptor. 235 */ 236 ufalloc() 237 { 238 register i; 239 240 for (i=0; i<NOFILE; i++) 241 if (u.u_ofile[i] == NULL) { 242 u.u_r.r_val1 = i; 243 u.u_pofile[i] = 0; 244 return (i); 245 } 246 u.u_error = EMFILE; 247 return (-1); 248 } 249 250 struct file *lastf; 251 /* 252 * Allocate a user file descriptor 253 * and a file structure. 254 * Initialize the descriptor 255 * to point at the file structure. 256 */ 257 struct file * 258 falloc() 259 { 260 register struct file *fp; 261 register i; 262 263 i = ufalloc(); 264 if (i < 0) 265 return (NULL); 266 if (lastf == 0) 267 lastf = file; 268 for (fp = lastf; fp < fileNFILE; fp++) 269 if (fp->f_count == 0) 270 goto slot; 271 for (fp = file; fp < lastf; fp++) 272 if (fp->f_count == 0) 273 goto slot; 274 tablefull("file"); 275 u.u_error = ENFILE; 276 return (NULL); 277 slot: 278 u.u_ofile[i] = fp; 279 fp->f_count++; 280 fp->f_offset = 0; 281 fp->f_inode = 0; 282 lastf = fp + 1; 283 return (fp); 284 } 285