1 /* kern_descrip.c 5.13 82/10/17 */ 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 16 #include "../h/descrip.h" 17 18 /* 19 * Descriptor management. 20 */ 21 22 /* 23 * TODO: 24 * getf should be renamed 25 * ufalloc side effects are gross 26 */ 27 28 /* 29 * System calls on descriptors. 30 */ 31 getdtablesize() 32 { 33 34 u.u_r.r_val1 = NOFILE; 35 } 36 37 getdprop() 38 { 39 register struct a { 40 int d; 41 struct dtype *dtypeb; 42 } *uap = (struct a *)u.u_ap; 43 register struct file *fp; 44 struct dtype adtype; 45 46 fp = getf(uap->d); 47 if (fp == 0) 48 return; 49 adtype.dt_type = 0; /* XXX */ 50 adtype.dt_protocol = 0; /* XXX */ 51 if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 52 sizeof (struct dtype)) < 0) { 53 u.u_error = EFAULT; 54 return; 55 } 56 } 57 58 getdopt() 59 { 60 61 } 62 63 setdopt() 64 { 65 66 } 67 68 dup() 69 { 70 register struct a { 71 int i; 72 } *uap = (struct a *) u.u_ap; 73 struct file *fp; 74 int j; 75 76 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 77 78 fp = getf(uap->i); 79 if (fp == 0) 80 return; 81 j = ufalloc(); 82 if (j < 0) 83 return; 84 dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 85 } 86 87 dup2() 88 { 89 register struct a { 90 int i, j; 91 } *uap = (struct a *) u.u_ap; 92 register struct file *fp; 93 94 fp = getf(uap->i); 95 if (fp == 0) 96 return; 97 if (uap->j < 0 || uap->j >= NOFILE) { 98 u.u_error = EBADF; 99 return; 100 } 101 u.u_r.r_val1 = uap->j; 102 if (uap->i == uap->j) 103 return; 104 if (u.u_ofile[uap->j]) { 105 closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); 106 if (u.u_error) 107 return; 108 /* u.u_ofile[uap->j] = 0; */ 109 /* u.u_pofile[uap->j] = 0; */ 110 } 111 dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 112 } 113 114 dupit(fd, fp, lockflags) 115 int fd; 116 register struct file *fp; 117 register int lockflags; 118 { 119 120 u.u_ofile[fd] = fp; 121 u.u_pofile[fd] = lockflags; 122 fp->f_count++; 123 if (lockflags&RDLOCK) 124 fp->f_inode->i_rdlockc++; 125 if (lockflags&WRLOCK) 126 fp->f_inode->i_wrlockc++; 127 } 128 129 close() 130 { 131 register struct a { 132 int i; 133 } *uap = (struct a *)u.u_ap; 134 register struct file *fp; 135 136 fp = getf(uap->i); 137 if (fp == 0) 138 return; 139 closef(fp, 0, u.u_pofile[uap->i]); 140 /* WHAT IF u.u_error ? */ 141 u.u_ofile[uap->i] = NULL; 142 u.u_pofile[uap->i] = 0; 143 } 144 145 wrap() 146 { 147 register struct a { 148 int d; 149 struct dtype *dtypeb; 150 } *uap = (struct a *)u.u_ap; 151 register struct file *fp; 152 struct dtype adtype; 153 154 fp = getf(uap->d); 155 if (fp == 0) 156 return; 157 if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 158 sizeof (struct dtype)) < 0) { 159 u.u_error = EFAULT; 160 return; 161 } 162 /* DO WRAP */ 163 } 164 165 int unselect(); 166 int nselcoll; 167 /* 168 * Select system call. 169 */ 170 select() 171 { 172 register struct uap { 173 int nd; 174 long *in; 175 long *ou; 176 long *ex; 177 struct timeval *tv; 178 } *uap = (struct uap *)u.u_ap; 179 int ibits[3], obits[3]; 180 struct timeval atv; 181 int s, ncoll; 182 label_t lqsave; 183 184 if (uap->nd >= NOFILE) { 185 u.u_error = EINVAL; 186 return; 187 } 188 189 #define getbits(name, x) \ 190 if (uap->name) { \ 191 if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 192 sizeof (ibits[x]))) { \ 193 u.u_error = EFAULT; \ 194 return; \ 195 } \ 196 } else \ 197 ibits[x] = 0; 198 getbits(in, 0); 199 getbits(ou, 1); 200 getbits(ex, 2); 201 #undef getbits 202 203 if (uap->tv) { 204 if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 205 u.u_error = EFAULT; 206 return; 207 } 208 if (itimerfix(&atv)) { 209 u.u_error = EINVAL; 210 return; 211 } 212 s = spl7(); timevaladd(&atv, &time); splx(s); 213 } 214 retry: 215 ncoll = nselcoll; 216 u.u_procp->p_flag |= SSEL; 217 u.u_r.r_val1 = selscan(ibits, obits); 218 if (u.u_error) 219 return; 220 if (u.u_r.r_val1) 221 goto done; 222 s = spl6(); 223 if (uap->tv && timercmp(&time, &atv, >=)) { 224 splx(s); 225 goto done; 226 } 227 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 228 u.u_procp->p_flag &= ~SSEL; 229 splx(s); 230 goto retry; 231 } 232 u.u_procp->p_flag &= ~SSEL; 233 if (uap->tv) { 234 lqsave = u.u_qsave; 235 if (setjmp(&u.u_qsave)) { 236 untimeout(unselect, (caddr_t)u.u_procp); 237 u.u_error = EINTR; 238 splx(s); 239 return; 240 } 241 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 242 } 243 sleep((caddr_t)&selwait, PZERO+1); 244 if (uap->tv) { 245 u.u_qsave = lqsave; 246 untimeout(unselect, (caddr_t)u.u_procp); 247 } 248 splx(s); 249 goto retry; 250 done: 251 #define putbits(name, x) \ 252 if (uap->name) { \ 253 if (copyout((caddr_t)obits[x], (caddr_t)uap->name, \ 254 sizeof (obits[x]))) { \ 255 u.u_error = EFAULT; \ 256 return; \ 257 } \ 258 } 259 putbits(in, 0); 260 putbits(ou, 1); 261 putbits(ex, 2); 262 #undef putbits 263 } 264 265 unselect(p) 266 register struct proc *p; 267 { 268 register int s = spl6(); 269 270 switch (p->p_stat) { 271 272 case SSLEEP: 273 setrun(p); 274 break; 275 276 case SSTOP: 277 unsleep(p); 278 break; 279 } 280 splx(s); 281 } 282 283 selscan(ibits, obits) 284 int *ibits, *obits; 285 { 286 register int which, bits, i; 287 int flag; 288 struct file *fp; 289 int able; 290 struct inode *ip; 291 int n = 0; 292 293 for (which = 0; which < 3; which++) { 294 bits = ibits[which]; 295 obits[which] = 0; 296 switch (which) { 297 298 case 0: 299 flag = FREAD; break; 300 301 case 1: 302 flag = FWRITE; break; 303 304 case 2: 305 flag = 0; break; 306 } 307 while (i = ffs(bits)) { 308 bits &= ~(1<<(i-1)); 309 fp = u.u_ofile[i-1]; 310 if (fp == NULL) { 311 u.u_error = EBADF; 312 break; 313 } 314 if (fp->f_type == DTYPE_SOCKET) 315 able = soselect(fp->f_socket, flag); 316 else { 317 ip = fp->f_inode; 318 switch (ip->i_mode & IFMT) { 319 320 case IFCHR: 321 able = 322 (*cdevsw[major(ip->i_rdev)].d_select) 323 (ip->i_rdev, flag); 324 break; 325 326 case IFBLK: 327 case IFREG: 328 case IFDIR: 329 able = 1; 330 break; 331 } 332 333 } 334 if (able) { 335 obits[which] |= (1<<(i-1)); 336 n++; 337 } 338 } 339 } 340 return (n); 341 } 342 343 /*ARGSUSED*/ 344 seltrue(dev, flag) 345 dev_t dev; 346 int flag; 347 { 348 349 return (1); 350 } 351 352 selwakeup(p, coll) 353 register struct proc *p; 354 int coll; 355 { 356 int s; 357 358 if (coll) { 359 nselcoll++; 360 wakeup((caddr_t)&selwait); 361 } 362 if (p) { 363 if (p->p_wchan == (caddr_t)&selwait) 364 setrun(p); 365 else { 366 s = spl6(); 367 if (p->p_flag & SSEL) 368 p->p_flag &= ~SSEL; 369 splx(s); 370 } 371 } 372 } 373 374 revoke() 375 { 376 377 /* XXX */ 378 } 379 380 /* 381 * Allocate a user file descriptor. 382 */ 383 ufalloc() 384 { 385 register i; 386 387 for (i=0; i<NOFILE; i++) 388 if (u.u_ofile[i] == NULL) { 389 u.u_r.r_val1 = i; 390 u.u_pofile[i] = 0; 391 return (i); 392 } 393 u.u_error = EMFILE; 394 return (-1); 395 } 396 397 struct file *lastf; 398 /* 399 * Allocate a user file descriptor 400 * and a file structure. 401 * Initialize the descriptor 402 * to point at the file structure. 403 */ 404 struct file * 405 falloc() 406 { 407 register struct file *fp; 408 register i; 409 410 i = ufalloc(); 411 if (i < 0) 412 return (NULL); 413 if (lastf == 0) 414 lastf = file; 415 for (fp = lastf; fp < fileNFILE; fp++) 416 if (fp->f_count == 0) 417 goto slot; 418 for (fp = file; fp < lastf; fp++) 419 if (fp->f_count == 0) 420 goto slot; 421 tablefull("file"); 422 u.u_error = ENFILE; 423 return (NULL); 424 slot: 425 u.u_ofile[i] = fp; 426 fp->f_count++; 427 fp->f_offset = 0; 428 fp->f_inode = 0; 429 lastf = fp + 1; 430 return (fp); 431 } 432 /* 433 * Convert a user supplied file descriptor into a pointer 434 * to a file structure. Only task is to check range of the descriptor. 435 * Critical paths should use the GETF macro, defined in inline.h. 436 */ 437 struct file * 438 getf(f) 439 register int f; 440 { 441 register struct file *fp; 442 443 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 444 u.u_error = EBADF; 445 return (NULL); 446 } 447 return (fp); 448 } 449 450 /* 451 * Internal form of close. 452 * Decrement reference count on 453 * file structure. 454 * Also make sure the pipe protocol 455 * does not constipate. 456 * 457 * Decrement reference count on the inode following 458 * removal to the referencing file structure. 459 * Call device handler on last close. 460 * Nouser indicates that the user isn't available to present 461 * errors to. 462 * 463 * Handling locking at this level is RIDICULOUS. 464 */ 465 closef(fp, nouser, flags) 466 register struct file *fp; 467 int nouser, flags; 468 { 469 register struct inode *ip; 470 register struct mount *mp; 471 int flag, mode; 472 dev_t dev; 473 register int (*cfunc)(); 474 475 if (fp == NULL) 476 return; 477 if (fp->f_count > 1) { 478 fp->f_count--; 479 return; 480 } 481 if (fp->f_type == DTYPE_SOCKET) { 482 u.u_error = 0; /* XXX */ 483 soclose(fp->f_socket, nouser); 484 if (nouser == 0 && u.u_error) 485 return; 486 fp->f_socket = 0; 487 fp->f_count = 0; 488 return; 489 } 490 flag = fp->f_flag; 491 ip = fp->f_inode; 492 dev = (dev_t)ip->i_rdev; 493 mode = ip->i_mode & IFMT; 494 flags &= RDLOCK|WRLOCK; /* conservative */ 495 if (flags) 496 funlocki(ip, flags); 497 ilock(ip); 498 iput(ip); 499 fp->f_count = 0; 500 501 switch (mode) { 502 503 case IFCHR: 504 cfunc = cdevsw[major(dev)].d_close; 505 break; 506 507 case IFBLK: 508 /* 509 * We don't want to really close the device if it is mounted 510 */ 511 for (mp = mount; mp < &mount[NMOUNT]; mp++) 512 if (mp->m_bufp != NULL && mp->m_dev == dev) 513 return; 514 cfunc = bdevsw[major(dev)].d_close; 515 break; 516 517 default: 518 return; 519 } 520 for (fp = file; fp < fileNFILE; fp++) { 521 if (fp->f_type == DTYPE_SOCKET) /* XXX */ 522 continue; 523 if (fp->f_count && (ip = fp->f_inode) && 524 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 525 return; 526 } 527 if (mode == IFBLK) { 528 /* 529 * On last close of a block device (that isn't mounted) 530 * we must invalidate any in core blocks 531 */ 532 bflush(dev); 533 binval(dev); 534 } 535 (*cfunc)(dev, flag, fp); 536 } 537 538 opause() 539 { 540 541 for (;;) 542 sleep((caddr_t)&u, PSLEP); 543 } 544