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