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