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