1 /* kern_descrip.c 5.23 83/01/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 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 if (u.u_pofile[uap->i] & UF_MAPPED) 141 munmapfd(uap->i); 142 closef(fp, 0, u.u_pofile[uap->i]); 143 /* WHAT IF u.u_error ? */ 144 u.u_ofile[uap->i] = NULL; 145 u.u_pofile[uap->i] = 0; 146 } 147 148 wrap() 149 { 150 register struct a { 151 int d; 152 struct dtype *dtypeb; 153 } *uap = (struct a *)u.u_ap; 154 register struct file *fp; 155 struct dtype adtype; 156 157 fp = getf(uap->d); 158 if (fp == 0) 159 return; 160 u.u_error = copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 161 sizeof (struct dtype)); 162 if (u.u_error) 163 return; 164 /* DO WRAP */ 165 } 166 167 int unselect(); 168 int nselcoll; 169 /* 170 * Select system call. 171 */ 172 select() 173 { 174 register struct uap { 175 int nd; 176 long *in; 177 long *ou; 178 long *ex; 179 struct timeval *tv; 180 } *uap = (struct uap *)u.u_ap; 181 int ibits[3], obits[3]; 182 struct timeval atv; 183 int s, ncoll; 184 label_t lqsave; 185 186 obits[0] = obits[1] = obits[2] = 0; 187 if (uap->nd > NOFILE) 188 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 189 190 #define getbits(name, x) \ 191 if (uap->name) { \ 192 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 193 sizeof (ibits[x])); \ 194 if (u.u_error) \ 195 goto done; \ 196 } else \ 197 ibits[x] = 0; 198 getbits(in, 0); 199 getbits(ou, 1); 200 getbits(ex, 2); 201 #undef getbits 202 203 if (uap->tv) { 204 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 205 sizeof (atv)); 206 if (u.u_error) 207 goto done; 208 if (itimerfix(&atv)) { 209 u.u_error = EINVAL; 210 goto done; 211 } 212 s = spl7(); timevaladd(&atv, &time); splx(s); 213 } 214 retry: 215 ncoll = nselcoll; 216 u.u_procp->p_flag |= SSEL; 217 u.u_r.r_val1 = selscan(ibits, obits); 218 if (u.u_error || u.u_r.r_val1) 219 goto done; 220 s = spl6(); 221 if (uap->tv && timercmp(&time, &atv, >=)) { 222 splx(s); 223 goto done; 224 } 225 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 226 u.u_procp->p_flag &= ~SSEL; 227 splx(s); 228 goto retry; 229 } 230 u.u_procp->p_flag &= ~SSEL; 231 if (uap->tv) { 232 lqsave = u.u_qsave; 233 if (setjmp(&u.u_qsave)) { 234 untimeout(unselect, (caddr_t)u.u_procp); 235 u.u_error = EINTR; 236 splx(s); 237 goto done; 238 } 239 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 240 } 241 sleep((caddr_t)&selwait, PZERO+1); 242 if (uap->tv) { 243 u.u_qsave = lqsave; 244 untimeout(unselect, (caddr_t)u.u_procp); 245 } 246 splx(s); 247 goto retry; 248 done: 249 #define putbits(name, x) \ 250 if (uap->name) { \ 251 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 252 sizeof (obits[x])); \ 253 if (error) \ 254 u.u_error = error; \ 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 354 if (coll) { 355 nselcoll++; 356 wakeup((caddr_t)&selwait); 357 } 358 if (p) { 359 int s = spl6(); 360 if (p->p_wchan == (caddr_t)&selwait) 361 setrun(p); 362 else if (p->p_flag & SSEL) 363 p->p_flag &= ~SSEL; 364 splx(s); 365 } 366 } 367 368 revoke() 369 { 370 371 /* XXX */ 372 } 373 374 /* 375 * Allocate a user file descriptor. 376 */ 377 ufalloc() 378 { 379 register i; 380 381 for (i=0; i<NOFILE; i++) 382 if (u.u_ofile[i] == NULL) { 383 u.u_r.r_val1 = i; 384 u.u_pofile[i] = 0; 385 return (i); 386 } 387 u.u_error = EMFILE; 388 return (-1); 389 } 390 391 struct file *lastf; 392 /* 393 * Allocate a user file descriptor 394 * and a file structure. 395 * Initialize the descriptor 396 * to point at the file structure. 397 */ 398 struct file * 399 falloc() 400 { 401 register struct file *fp; 402 register i; 403 404 i = ufalloc(); 405 if (i < 0) 406 return (NULL); 407 if (lastf == 0) 408 lastf = file; 409 for (fp = lastf; fp < fileNFILE; fp++) 410 if (fp->f_count == 0) 411 goto slot; 412 for (fp = file; fp < lastf; fp++) 413 if (fp->f_count == 0) 414 goto slot; 415 tablefull("file"); 416 u.u_error = ENFILE; 417 return (NULL); 418 slot: 419 u.u_ofile[i] = fp; 420 fp->f_count++; 421 fp->f_offset = 0; 422 fp->f_inode = 0; 423 lastf = fp + 1; 424 return (fp); 425 } 426 /* 427 * Convert a user supplied file descriptor into a pointer 428 * to a file structure. Only task is to check range of the descriptor. 429 * Critical paths should use the GETF macro, defined in inline.h. 430 */ 431 struct file * 432 getf(f) 433 register int f; 434 { 435 register struct file *fp; 436 437 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 438 u.u_error = EBADF; 439 return (NULL); 440 } 441 return (fp); 442 } 443 444 /* 445 * Internal form of close. 446 * Decrement reference count on 447 * file structure. 448 * Also make sure the pipe protocol 449 * does not constipate. 450 * 451 * Decrement reference count on the inode following 452 * removal to the referencing file structure. 453 * Call device handler on last close. 454 * Nouser indicates that the user isn't available to present 455 * errors to. 456 * 457 * Handling locking at this level is RIDICULOUS. 458 */ 459 closef(fp, nouser, flags) 460 register struct file *fp; 461 int nouser, flags; 462 { 463 register struct inode *ip; 464 register struct mount *mp; 465 int flag, mode; 466 dev_t dev; 467 register int (*cfunc)(); 468 469 if (fp == NULL) 470 return; 471 if (fp->f_count > 1) { 472 fp->f_count--; 473 return; 474 } 475 if (fp->f_type == DTYPE_SOCKET) { 476 u.u_error = soclose(fp->f_socket, nouser); 477 if (nouser == 0 && u.u_error) 478 return; 479 fp->f_socket = 0; 480 fp->f_count = 0; 481 return; 482 } 483 flag = fp->f_flag; 484 ip = fp->f_inode; 485 dev = (dev_t)ip->i_rdev; 486 mode = ip->i_mode & IFMT; 487 flags &= UF_SHLOCK|UF_EXLOCK; /* conservative */ 488 if (flags) 489 funlocki(ip, flags); 490 ilock(ip); 491 iput(ip); 492 fp->f_count = 0; 493 494 switch (mode) { 495 496 case IFCHR: 497 cfunc = cdevsw[major(dev)].d_close; 498 break; 499 500 case IFBLK: 501 /* 502 * We don't want to really close the device if it is mounted 503 */ 504 for (mp = mount; mp < &mount[NMOUNT]; mp++) 505 if (mp->m_bufp != NULL && mp->m_dev == dev) 506 return; 507 cfunc = bdevsw[major(dev)].d_close; 508 break; 509 510 default: 511 return; 512 } 513 for (fp = file; fp < fileNFILE; fp++) { 514 if (fp->f_type == DTYPE_SOCKET) /* XXX */ 515 continue; 516 if (fp->f_count && (ip = fp->f_inode) && 517 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 518 return; 519 } 520 if (mode == IFBLK) { 521 /* 522 * On last close of a block device (that isn't mounted) 523 * we must invalidate any in core blocks 524 */ 525 bflush(dev); 526 binval(dev); 527 } 528 (*cfunc)(dev, flag, fp); 529 } 530 531 opause() 532 { 533 534 for (;;) 535 sleep((caddr_t)&u, PSLEP); 536 } 537