1 /* vfs_vnops.c 4.4 02/01/81 */ 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 #ifdef UCBIPC 33 if (u.u_pofile[f] & ISPORT) { 34 u.u_error = EISPORT; 35 return (NULL); 36 } 37 #endif 38 return (fp); 39 } 40 41 /* 42 * Internal form of close. 43 * Decrement reference count on 44 * file structure. 45 * Also make sure the pipe protocol 46 * does not constipate. 47 * 48 * Decrement reference count on the inode following 49 * removal to the referencing file structure. 50 * Call device handler on last close. 51 */ 52 closef(fp) 53 register struct file *fp; 54 { 55 register struct inode *ip; 56 register struct mount *mp; 57 int flag, mode; 58 dev_t dev; 59 register int (*cfunc)(); 60 61 if(fp == NULL) 62 return; 63 if (fp->f_count > 1) { 64 fp->f_count--; 65 return; 66 } 67 ip = fp->f_inode; 68 flag = fp->f_flag; 69 dev = (dev_t)ip->i_un.i_rdev; 70 mode = ip->i_mode & IFMT; 71 72 plock(ip); 73 fp->f_count = 0; 74 if(flag & FPIPE) { 75 ip->i_mode &= ~(IREAD|IWRITE); 76 wakeup((caddr_t)ip+1); 77 wakeup((caddr_t)ip+2); 78 } 79 iput(ip); 80 81 switch(mode) { 82 83 case IFCHR: 84 case IFMPC: 85 cfunc = cdevsw[major(dev)].d_close; 86 break; 87 88 case IFBLK: 89 /* 90 * We don't want to really close the device if it is mounted 91 */ 92 for (mp = mount; mp < &mount[NMOUNT]; mp++) 93 if (mp->m_bufp != NULL && mp->m_dev == dev) 94 return; 95 case IFMPB: 96 cfunc = bdevsw[major(dev)].d_close; 97 break; 98 default: 99 return; 100 } 101 102 if ((flag & FMP) == 0) { 103 for(fp=file; fp < &file[NFILE]; fp++) 104 if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev && 105 (ip->i_mode&IFMT) == mode) 106 return; 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 } 116 (*cfunc)(dev, flag, fp); 117 } 118 119 /* 120 * openi called to allow handler 121 * of special files to initialize and 122 * validate before actual IO. 123 */ 124 openi(ip, rw) 125 register struct inode *ip; 126 { 127 dev_t dev; 128 register unsigned int maj; 129 130 dev = (dev_t)ip->i_un.i_rdev; 131 maj = major(dev); 132 switch(ip->i_mode&IFMT) { 133 134 case IFCHR: 135 case IFMPC: 136 if(maj >= nchrdev) 137 goto bad; 138 (*cdevsw[maj].d_open)(dev, rw); 139 break; 140 141 case IFBLK: 142 case IFMPB: 143 if(maj >= nblkdev) 144 goto bad; 145 (*bdevsw[maj].d_open)(dev, rw); 146 } 147 return; 148 149 bad: 150 u.u_error = ENXIO; 151 } 152 153 /* 154 * Check mode permission on inode pointer. 155 * Mode is READ, WRITE or EXEC. 156 * In the case of WRITE, the 157 * read-only status of the file 158 * system is checked. 159 * Also in WRITE, prototype text 160 * segments cannot be written. 161 * The mode is shifted to select 162 * the owner/group/other fields. 163 * The super user is granted all 164 * permissions. 165 */ 166 access(ip, mode) 167 register struct inode *ip; 168 { 169 register m; 170 171 m = mode; 172 if(m == IWRITE) { 173 if(getfs(ip->i_dev)->s_ronly != 0) { 174 u.u_error = EROFS; 175 return(1); 176 } 177 if (ip->i_flag&ITEXT) /* try to free text */ 178 xrele(ip); 179 if(ip->i_flag & ITEXT) { 180 u.u_error = ETXTBSY; 181 return(1); 182 } 183 } 184 if(u.u_uid == 0) 185 return(0); 186 if(u.u_uid != ip->i_uid) { 187 m >>= 3; 188 if(u.u_gid != ip->i_gid) 189 m >>= 3; 190 } 191 if((ip->i_mode&m) != 0) 192 return(0); 193 194 u.u_error = EACCES; 195 return(1); 196 } 197 198 /* 199 * Look up a pathname and test if 200 * the resultant inode is owned by the 201 * current user. 202 * If not, try for super-user. 203 * If permission is granted, 204 * return inode pointer. 205 */ 206 struct inode * 207 owner() 208 { 209 register struct inode *ip; 210 211 ip = namei(uchar, 0); 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 = &file[0]; 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 * no file -- if there are no available 262 * file structures. 263 */ 264 struct file * 265 falloc() 266 { 267 register struct file *fp; 268 register i; 269 270 i = ufalloc(); 271 if(i < 0) 272 return(NULL); 273 for(fp = lastf; fp < &file[NFILE]; fp++) 274 if(fp->f_count == 0) 275 goto slot; 276 for(fp = &file[0]; fp < lastf; fp++) 277 if(fp->f_count == 0) 278 goto slot; 279 printf("no file\n"); 280 u.u_error = ENFILE; 281 return(NULL); 282 slot: 283 u.u_ofile[i] = fp; 284 fp->f_count++; 285 fp->f_un.f_offset = 0; 286 lastf = fp + 1; 287 return(fp); 288 } 289