1 /* vfs_vnops.c 4.22 82/02/27 */ 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(follow) 207 int follow; 208 { 209 register struct inode *ip; 210 211 ip = namei(uchar, 0, follow); 212 if (ip == NULL) 213 return (NULL); 214 if (u.u_uid == ip->i_uid) 215 return (ip); 216 if (suser()) 217 return (ip); 218 iput(ip); 219 return (NULL); 220 } 221 222 /* 223 * Test if the current user is the 224 * super user. 225 */ 226 suser() 227 { 228 229 if (u.u_uid == 0) { 230 u.u_acflag |= ASU; 231 return (1); 232 } 233 u.u_error = EPERM; 234 return (0); 235 } 236 237 /* 238 * Allocate a user file descriptor. 239 */ 240 ufalloc() 241 { 242 register i; 243 244 for (i=0; i<NOFILE; i++) 245 if (u.u_ofile[i] == NULL) { 246 u.u_r.r_val1 = i; 247 u.u_pofile[i] = 0; 248 return (i); 249 } 250 u.u_error = EMFILE; 251 return (-1); 252 } 253 254 struct file *lastf; 255 /* 256 * Allocate a user file descriptor 257 * and a file structure. 258 * Initialize the descriptor 259 * to point at the file structure. 260 */ 261 struct file * 262 falloc() 263 { 264 register struct file *fp; 265 register i; 266 267 i = ufalloc(); 268 if (i < 0) 269 return (NULL); 270 if (lastf == 0) 271 lastf = file; 272 for (fp = lastf; fp < fileNFILE; fp++) 273 if (fp->f_count == 0) 274 goto slot; 275 for (fp = file; fp < lastf; fp++) 276 if (fp->f_count == 0) 277 goto slot; 278 tablefull("file"); 279 u.u_error = ENFILE; 280 return (NULL); 281 slot: 282 u.u_ofile[i] = fp; 283 fp->f_count++; 284 fp->f_offset = 0; 285 fp->f_inode = 0; 286 lastf = fp + 1; 287 return (fp); 288 } 289