1 /* kern_descrip.c 5.15 82/10/22 */ 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 obits[0] = obits[1] = obits[2] = 0; 185 if (uap->nd >= NOFILE) { 186 u.u_error = EINVAL; 187 goto done; 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 goto done; \ 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 goto done; 208 } 209 if (itimerfix(&atv)) { 210 u.u_error = EINVAL; 211 goto done; 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 || u.u_r.r_val1) 220 goto done; 221 s = spl6(); 222 if (uap->tv && timercmp(&time, &atv, >=)) { 223 splx(s); 224 goto done; 225 } 226 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 227 u.u_procp->p_flag &= ~SSEL; 228 splx(s); 229 goto retry; 230 } 231 u.u_procp->p_flag &= ~SSEL; 232 if (uap->tv) { 233 lqsave = u.u_qsave; 234 if (setjmp(&u.u_qsave)) { 235 untimeout(unselect, (caddr_t)u.u_procp); 236 u.u_error = EINTR; 237 splx(s); 238 goto done; 239 } 240 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 241 } 242 sleep((caddr_t)&selwait, PZERO+1); 243 if (uap->tv) { 244 u.u_qsave = lqsave; 245 untimeout(unselect, (caddr_t)u.u_procp); 246 } 247 splx(s); 248 goto retry; 249 done: 250 #define putbits(name, x) \ 251 if (uap->name) { \ 252 if (copyout((caddr_t)obits[x], (caddr_t)uap->name, \ 253 sizeof (obits[x]))) \ 254 u.u_error = EFAULT; \ 255 } 256 putbits(in, 0); 257 putbits(ou, 1); 258 putbits(ex, 2); 259 #undef putbits 260 } 261 262 unselect(p) 263 register struct proc *p; 264 { 265 register int s = spl6(); 266 267 switch (p->p_stat) { 268 269 case SSLEEP: 270 setrun(p); 271 break; 272 273 case SSTOP: 274 unsleep(p); 275 break; 276 } 277 splx(s); 278 } 279 280 selscan(ibits, obits) 281 int *ibits, *obits; 282 { 283 register int which, bits, i; 284 int flag; 285 struct file *fp; 286 int able; 287 struct inode *ip; 288 int n = 0; 289 290 for (which = 0; which < 3; which++) { 291 bits = ibits[which]; 292 obits[which] = 0; 293 switch (which) { 294 295 case 0: 296 flag = FREAD; break; 297 298 case 1: 299 flag = FWRITE; break; 300 301 case 2: 302 flag = 0; break; 303 } 304 while (i = ffs(bits)) { 305 bits &= ~(1<<(i-1)); 306 fp = u.u_ofile[i-1]; 307 if (fp == NULL) { 308 u.u_error = EBADF; 309 break; 310 } 311 if (fp->f_type == DTYPE_SOCKET) 312 able = soselect(fp->f_socket, flag); 313 else { 314 ip = fp->f_inode; 315 switch (ip->i_mode & IFMT) { 316 317 case IFCHR: 318 able = 319 (*cdevsw[major(ip->i_rdev)].d_select) 320 (ip->i_rdev, flag); 321 break; 322 323 case IFBLK: 324 case IFREG: 325 case IFDIR: 326 able = 1; 327 break; 328 } 329 330 } 331 if (able) { 332 obits[which] |= (1<<(i-1)); 333 n++; 334 } 335 } 336 } 337 return (n); 338 } 339 340 /*ARGSUSED*/ 341 seltrue(dev, flag) 342 dev_t dev; 343 int flag; 344 { 345 346 return (1); 347 } 348 349 selwakeup(p, coll) 350 register struct proc *p; 351 int coll; 352 { 353 int s; 354 355 if (coll) { 356 nselcoll++; 357 wakeup((caddr_t)&selwait); 358 } 359 if (p) { 360 if (p->p_wchan == (caddr_t)&selwait) 361 setrun(p); 362 else { 363 s = spl6(); 364 if (p->p_flag & SSEL) 365 p->p_flag &= ~SSEL; 366 splx(s); 367 } 368 } 369 } 370 371 revoke() 372 { 373 374 /* XXX */ 375 } 376 377 /* 378 * Allocate a user file descriptor. 379 */ 380 ufalloc() 381 { 382 register i; 383 384 for (i=0; i<NOFILE; i++) 385 if (u.u_ofile[i] == NULL) { 386 u.u_r.r_val1 = i; 387 u.u_pofile[i] = 0; 388 return (i); 389 } 390 u.u_error = EMFILE; 391 return (-1); 392 } 393 394 struct file *lastf; 395 /* 396 * Allocate a user file descriptor 397 * and a file structure. 398 * Initialize the descriptor 399 * to point at the file structure. 400 */ 401 struct file * 402 falloc() 403 { 404 register struct file *fp; 405 register i; 406 407 i = ufalloc(); 408 if (i < 0) 409 return (NULL); 410 if (lastf == 0) 411 lastf = file; 412 for (fp = lastf; fp < fileNFILE; fp++) 413 if (fp->f_count == 0) 414 goto slot; 415 for (fp = file; fp < lastf; fp++) 416 if (fp->f_count == 0) 417 goto slot; 418 tablefull("file"); 419 u.u_error = ENFILE; 420 return (NULL); 421 slot: 422 u.u_ofile[i] = fp; 423 fp->f_count++; 424 fp->f_offset = 0; 425 fp->f_inode = 0; 426 lastf = fp + 1; 427 return (fp); 428 } 429 /* 430 * Convert a user supplied file descriptor into a pointer 431 * to a file structure. Only task is to check range of the descriptor. 432 * Critical paths should use the GETF macro, defined in inline.h. 433 */ 434 struct file * 435 getf(f) 436 register int f; 437 { 438 register struct file *fp; 439 440 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 441 u.u_error = EBADF; 442 return (NULL); 443 } 444 return (fp); 445 } 446 447 /* 448 * Internal form of close. 449 * Decrement reference count on 450 * file structure. 451 * Also make sure the pipe protocol 452 * does not constipate. 453 * 454 * Decrement reference count on the inode following 455 * removal to the referencing file structure. 456 * Call device handler on last close. 457 * Nouser indicates that the user isn't available to present 458 * errors to. 459 * 460 * Handling locking at this level is RIDICULOUS. 461 */ 462 closef(fp, nouser, flags) 463 register struct file *fp; 464 int nouser, flags; 465 { 466 register struct inode *ip; 467 register struct mount *mp; 468 int flag, mode; 469 dev_t dev; 470 register int (*cfunc)(); 471 472 if (fp == NULL) 473 return; 474 if (fp->f_count > 1) { 475 fp->f_count--; 476 return; 477 } 478 if (fp->f_type == DTYPE_SOCKET) { 479 u.u_error = soclose(fp->f_socket, nouser); 480 if (nouser == 0 && u.u_error) 481 return; 482 fp->f_socket = 0; 483 fp->f_count = 0; 484 return; 485 } 486 flag = fp->f_flag; 487 ip = fp->f_inode; 488 dev = (dev_t)ip->i_rdev; 489 mode = ip->i_mode & IFMT; 490 flags &= RDLOCK|WRLOCK; /* conservative */ 491 if (flags) 492 funlocki(ip, flags); 493 ilock(ip); 494 iput(ip); 495 fp->f_count = 0; 496 497 switch (mode) { 498 499 case IFCHR: 500 cfunc = cdevsw[major(dev)].d_close; 501 break; 502 503 case IFBLK: 504 /* 505 * We don't want to really close the device if it is mounted 506 */ 507 for (mp = mount; mp < &mount[NMOUNT]; mp++) 508 if (mp->m_bufp != NULL && mp->m_dev == dev) 509 return; 510 cfunc = bdevsw[major(dev)].d_close; 511 break; 512 513 default: 514 return; 515 } 516 for (fp = file; fp < fileNFILE; fp++) { 517 if (fp->f_type == DTYPE_SOCKET) /* XXX */ 518 continue; 519 if (fp->f_count && (ip = fp->f_inode) && 520 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 521 return; 522 } 523 if (mode == IFBLK) { 524 /* 525 * On last close of a block device (that isn't mounted) 526 * we must invalidate any in core blocks 527 */ 528 bflush(dev); 529 binval(dev); 530 } 531 (*cfunc)(dev, flag, fp); 532 } 533 534 opause() 535 { 536 537 for (;;) 538 sleep((caddr_t)&u, PSLEP); 539 } 540