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