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