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