1 /* kern_descrip.c 5.26 83/06/14 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/kernel.h" 8 #include "../h/inode.h" 9 #include "../h/proc.h" 10 #include "../h/conf.h" 11 #include "../h/file.h" 12 #include "../h/socket.h" 13 #include "../h/socketvar.h" 14 #include "../h/mount.h" 15 #include "../h/stat.h" 16 17 #include "../h/ioctl.h" 18 19 /* 20 * Descriptor management. 21 */ 22 23 /* 24 * TODO: 25 * increase NOFILE 26 * eliminate u.u_error side effects 27 */ 28 29 /* 30 * System calls on descriptors. 31 */ 32 getdtablesize() 33 { 34 35 u.u_r.r_val1 = NOFILE; 36 } 37 38 getdopt() 39 { 40 41 } 42 43 setdopt() 44 { 45 46 } 47 48 dup() 49 { 50 register struct a { 51 int i; 52 } *uap = (struct a *) u.u_ap; 53 struct file *fp; 54 int j; 55 56 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 57 58 fp = getf(uap->i); 59 if (fp == 0) 60 return; 61 j = ufalloc(0); 62 if (j < 0) 63 return; 64 dupit(j, fp, u.u_pofile[uap->i]); 65 } 66 67 dup2() 68 { 69 register struct a { 70 int i, j; 71 } *uap = (struct a *) u.u_ap; 72 register struct file *fp; 73 74 fp = getf(uap->i); 75 if (fp == 0) 76 return; 77 if (uap->j < 0 || uap->j >= NOFILE) { 78 u.u_error = EBADF; 79 return; 80 } 81 u.u_r.r_val1 = uap->j; 82 if (uap->i == uap->j) 83 return; 84 if (u.u_ofile[uap->j]) { 85 if (u.u_pofile[uap->j] & UF_MAPPED) 86 munmapfd(uap->j); 87 closef(u.u_ofile[uap->j]); 88 if (u.u_error) 89 return; 90 } 91 dupit(uap->j, fp, u.u_pofile[uap->i]); 92 } 93 94 dupit(fd, fp, flags) 95 int fd; 96 register struct file *fp; 97 register int flags; 98 { 99 100 u.u_ofile[fd] = fp; 101 u.u_pofile[fd] = flags; 102 fp->f_count++; 103 } 104 105 /* 106 * The file control system call. 107 */ 108 fcntl() 109 { 110 register struct file *fp; 111 register struct a { 112 int fdes; 113 int cmd; 114 int arg; 115 } *uap; 116 register i; 117 register char *pop; 118 119 uap = (struct a *)u.u_ap; 120 fp = getf(uap->fdes); 121 if (fp == NULL) 122 return; 123 pop = &u.u_pofile[uap->fdes]; 124 switch(uap->cmd) { 125 case 0: 126 i = uap->arg; 127 if (i < 0 || i > NOFILE) { 128 u.u_error = EINVAL; 129 return; 130 } 131 if ((i = ufalloc(i)) < 0) 132 return; 133 dupit(i, fp, *pop); 134 break; 135 136 case 1: 137 u.u_r.r_val1 = *pop & 1; 138 break; 139 140 case 2: 141 *pop = (*pop &~ 1) | (uap->arg & 1); 142 break; 143 144 case 3: 145 u.u_r.r_val1 = fp->f_flag+FOPEN; 146 break; 147 148 case 4: 149 fp->f_flag &= FCNTLCANT; 150 fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 151 u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 152 if (u.u_error) 153 break; 154 u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 155 if (u.u_error) 156 (void) fset(fp, FNDELAY, 0); 157 break; 158 159 case 5: 160 u.u_error = fsetown(fp, uap->arg); 161 break; 162 163 case 6: 164 u.u_error = fgetown(fp, &u.u_r.r_val1); 165 break; 166 167 default: 168 u.u_error = EINVAL; 169 } 170 } 171 172 fset(fp, bit, value) 173 struct file *fp; 174 int bit, value; 175 { 176 177 if (value) 178 fp->f_flag |= bit; 179 else 180 fp->f_flag &= ~bit; 181 return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 182 (caddr_t)&value)); 183 } 184 185 fgetown(fp, valuep) 186 struct file *fp; 187 int *valuep; 188 { 189 int error; 190 191 switch (fp->f_type) { 192 193 case DTYPE_SOCKET: 194 *valuep = ((struct socket *)fp->f_data)->so_pgrp; 195 return (0); 196 197 default: 198 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 199 *valuep = -*valuep; 200 return (error); 201 } 202 } 203 204 fsetown(fp, value) 205 struct file *fp; 206 int value; 207 { 208 209 if (fp->f_type == DTYPE_SOCKET) { 210 ((struct socket *)fp->f_data)->so_pgrp = value; 211 return (0); 212 } 213 if (value > 0) { 214 struct proc *p = pfind(value); 215 if (p == 0) 216 return (EINVAL); 217 value = p->p_pgrp; 218 } else 219 value = -value; 220 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 221 } 222 223 fioctl(fp, cmd, value) 224 struct file *fp; 225 int cmd; 226 caddr_t value; 227 { 228 229 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 230 } 231 232 close() 233 { 234 register struct a { 235 int i; 236 } *uap = (struct a *)u.u_ap; 237 register struct file *fp; 238 register u_char *pf; 239 240 fp = getf(uap->i); 241 if (fp == 0) 242 return; 243 pf = (u_char *)&u.u_pofile[uap->i]; 244 if (*pf & UF_MAPPED) 245 munmapfd(uap->i); 246 closef(fp); 247 /* WHAT IF u.u_error ? */ 248 u.u_ofile[uap->i] = NULL; 249 *pf = 0; 250 } 251 252 fstat() 253 { 254 register struct file *fp; 255 register struct a { 256 int fdes; 257 struct stat *sb; 258 } *uap; 259 struct stat ub; 260 261 uap = (struct a *)u.u_ap; 262 fp = getf(uap->fdes); 263 if (fp == 0) 264 return; 265 switch (fp->f_type) { 266 267 case DTYPE_INODE: 268 u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 269 break; 270 271 case DTYPE_SOCKET: 272 u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 273 break; 274 275 default: 276 panic("fstat"); 277 /*NOTREACHED*/ 278 } 279 if (u.u_error == 0) 280 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 281 sizeof (ub)); 282 } 283 284 /* 285 * Allocate a user file descriptor. 286 */ 287 ufalloc(i) 288 register int i; 289 { 290 291 for (; i < NOFILE; i++) 292 if (u.u_ofile[i] == NULL) { 293 u.u_r.r_val1 = i; 294 u.u_pofile[i] = 0; 295 return (i); 296 } 297 u.u_error = EMFILE; 298 return (-1); 299 } 300 301 ufavail() 302 { 303 register int i, avail = 0; 304 305 for (i = 0; i < NOFILE; i++) 306 if (u.u_ofile[i] == NULL) 307 avail++; 308 return (avail); 309 } 310 311 struct file *lastf; 312 /* 313 * Allocate a user file descriptor 314 * and a file structure. 315 * Initialize the descriptor 316 * to point at the file structure. 317 */ 318 struct file * 319 falloc() 320 { 321 register struct file *fp; 322 register i; 323 324 i = ufalloc(0); 325 if (i < 0) 326 return (NULL); 327 if (lastf == 0) 328 lastf = file; 329 for (fp = lastf; fp < fileNFILE; fp++) 330 if (fp->f_count == 0) 331 goto slot; 332 for (fp = file; fp < lastf; fp++) 333 if (fp->f_count == 0) 334 goto slot; 335 tablefull("file"); 336 u.u_error = ENFILE; 337 return (NULL); 338 slot: 339 u.u_ofile[i] = fp; 340 fp->f_count = 1; 341 fp->f_data = 0; 342 fp->f_offset = 0; 343 lastf = fp + 1; 344 return (fp); 345 } 346 347 /* 348 * Convert a user supplied file descriptor into a pointer 349 * to a file structure. Only task is to check range of the descriptor. 350 * Critical paths should use the GETF macro. 351 */ 352 struct file * 353 getf(f) 354 register int f; 355 { 356 register struct file *fp; 357 358 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 359 u.u_error = EBADF; 360 return (NULL); 361 } 362 return (fp); 363 } 364 365 /* 366 * Internal form of close. 367 * Decrement reference count on file structure. 368 * If last reference not going away, but no more 369 * references except in message queues, run a 370 * garbage collect. This would better be done by 371 * forcing a gc() to happen sometime soon, rather 372 * than running one each time. 373 */ 374 closef(fp) 375 register struct file *fp; 376 { 377 378 if (fp == NULL) 379 return; 380 if (fp->f_count > 1) { 381 fp->f_count--; 382 if (fp->f_count == fp->f_msgcount) 383 unp_gc(); 384 return; 385 } 386 (*fp->f_ops->fo_close)(fp); 387 fp->f_count = 0; 388 } 389 390 /* 391 * Apply an advisory lock on a file descriptor. 392 */ 393 flock() 394 { 395 register struct a { 396 int fd; 397 int how; 398 } *uap = (struct a *)u.u_ap; 399 register struct file *fp; 400 401 fp = getf(uap->fd); 402 if (fp == NULL) 403 return; 404 if (fp->f_type != DTYPE_INODE) { 405 u.u_error = EOPNOTSUPP; 406 return; 407 } 408 if (uap->how & LOCK_UN) { 409 ino_unlock(fp, FSHLOCK|FEXLOCK); 410 return; 411 } 412 /* avoid work... */ 413 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 414 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 415 return; 416 u.u_error = ino_lock(fp, uap->how); 417 } 418