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