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