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