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