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