1 /* kern_descrip.c 5.20 82/12/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] & (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 if (u.u_pofile[uap->j] & UF_MAPPED) 106 munmapfd(uap->j); 107 closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); 108 if (u.u_error) 109 return; 110 /* u.u_ofile[uap->j] = 0; */ 111 /* u.u_pofile[uap->j] = 0; */ 112 } 113 dupit(uap->j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK)); 114 } 115 116 dupit(fd, fp, lockflags) 117 int fd; 118 register struct file *fp; 119 register int lockflags; 120 { 121 122 u.u_ofile[fd] = fp; 123 u.u_pofile[fd] = lockflags; 124 fp->f_count++; 125 if (lockflags&UF_SHLOCK) 126 fp->f_inode->i_shlockc++; 127 if (lockflags&UF_EXLOCK) 128 fp->f_inode->i_exlockc++; 129 } 130 131 close() 132 { 133 register struct a { 134 int i; 135 } *uap = (struct a *)u.u_ap; 136 register struct file *fp; 137 138 fp = getf(uap->i); 139 if (fp == 0) 140 return; 141 #ifdef SUNMMAP 142 if (u.u_pofile[uap->i] & UF_MAPPED) 143 munmapfd(uap->i); 144 #endif 145 closef(fp, 0, u.u_pofile[uap->i]); 146 /* WHAT IF u.u_error ? */ 147 u.u_ofile[uap->i] = NULL; 148 u.u_pofile[uap->i] = 0; 149 } 150 151 wrap() 152 { 153 register struct a { 154 int d; 155 struct dtype *dtypeb; 156 } *uap = (struct a *)u.u_ap; 157 register struct file *fp; 158 struct dtype adtype; 159 160 fp = getf(uap->d); 161 if (fp == 0) 162 return; 163 if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 164 sizeof (struct dtype)) < 0) { 165 u.u_error = EFAULT; 166 return; 167 } 168 /* DO WRAP */ 169 } 170 171 int unselect(); 172 int nselcoll; 173 /* 174 * Select system call. 175 */ 176 select() 177 { 178 register struct uap { 179 int nd; 180 long *in; 181 long *ou; 182 long *ex; 183 struct timeval *tv; 184 } *uap = (struct uap *)u.u_ap; 185 int ibits[3], obits[3]; 186 struct timeval atv; 187 int s, ncoll; 188 label_t lqsave; 189 190 obits[0] = obits[1] = obits[2] = 0; 191 if (uap->nd > NOFILE) 192 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 193 194 #define getbits(name, x) \ 195 if (uap->name) { \ 196 if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 197 sizeof (ibits[x]))) { \ 198 u.u_error = EFAULT; \ 199 goto done; \ 200 } \ 201 } else \ 202 ibits[x] = 0; 203 getbits(in, 0); 204 getbits(ou, 1); 205 getbits(ex, 2); 206 #undef getbits 207 208 if (uap->tv) { 209 if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 210 u.u_error = EFAULT; 211 goto done; 212 } 213 if (itimerfix(&atv)) { 214 u.u_error = EINVAL; 215 goto done; 216 } 217 s = spl7(); timevaladd(&atv, &time); splx(s); 218 } 219 retry: 220 ncoll = nselcoll; 221 u.u_procp->p_flag |= SSEL; 222 u.u_r.r_val1 = selscan(ibits, obits); 223 if (u.u_error || u.u_r.r_val1) 224 goto done; 225 s = spl6(); 226 if (uap->tv && timercmp(&time, &atv, >=)) { 227 splx(s); 228 goto done; 229 } 230 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 231 u.u_procp->p_flag &= ~SSEL; 232 splx(s); 233 goto retry; 234 } 235 u.u_procp->p_flag &= ~SSEL; 236 if (uap->tv) { 237 lqsave = u.u_qsave; 238 if (setjmp(&u.u_qsave)) { 239 untimeout(unselect, (caddr_t)u.u_procp); 240 u.u_error = EINTR; 241 splx(s); 242 goto done; 243 } 244 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 245 } 246 sleep((caddr_t)&selwait, PZERO+1); 247 if (uap->tv) { 248 u.u_qsave = lqsave; 249 untimeout(unselect, (caddr_t)u.u_procp); 250 } 251 splx(s); 252 goto retry; 253 done: 254 #define putbits(name, x) \ 255 if (uap->name) { \ 256 if (copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 257 sizeof (obits[x]))) \ 258 u.u_error = EFAULT; \ 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 = 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 &= UF_SHLOCK|UF_EXLOCK; /* 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