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