1 /* kern_descrip.c 5.2 82/07/24 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/inode.h" 8 #include "../h/proc.h" 9 #include "../h/conf.h" 10 #include "../h/file.h" 11 #include "../h/inline.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 dstd() 32 { 33 34 u.u_r.r_val1 = NOFILE; 35 } 36 37 dup() 38 { 39 register struct a { 40 int i; 41 } *uap = (struct a *) u.u_ap; 42 register struct file *fp; 43 register int j; 44 45 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 46 47 fp = getf(uap->i); 48 if (fp == 0) 49 return; 50 j = ufalloc(); 51 if (j < 0) 52 return; 53 u.u_ofile[j] = fp; 54 fp->f_count++; 55 } 56 57 dup2() 58 { 59 register struct a { 60 int i, j; 61 } *uap = (struct a *) u.u_ap; 62 register struct file *fp; 63 64 fp = getf(uap->i); 65 if (fp == 0) 66 return; 67 if (uap->j < 0 || uap->j >= NOFILE) { 68 u.u_error = EBADF; 69 return; 70 } 71 u.u_r.r_val1 = uap->j; 72 if (uap->i == uap->j) 73 return; 74 if (u.u_ofile[uap->j]) { 75 closef(u.u_ofile[uap->j], 0); 76 if (u.u_error) 77 return; 78 /* u.u_ofile[uap->j] = 0; */ 79 } 80 u.u_ofile[uap->j] = fp; 81 fp->f_count++; 82 } 83 84 close() 85 { 86 register struct a { 87 int i; 88 } *uap = (struct a *)u.u_ap; 89 register struct file *fp; 90 91 fp = getf(uap->i); 92 if (fp == 0) 93 return; 94 u.u_ofile[uap->i] = 0; 95 closef(fp, 0); 96 /* WHAT IF u.u_error ? */ 97 } 98 99 dtype() 100 { 101 register struct a { 102 int d; 103 struct dtype *dtypeb; 104 } *uap = (struct a *)u.u_ap; 105 register struct file *fp; 106 struct dtype adtype; 107 108 fp = getf(uap->d); 109 if (fp == 0) 110 return; 111 adtype.dt_type = 0; /* XXX */ 112 adtype.dt_protocol = 0; /* XXX */ 113 if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 114 sizeof (struct dtype)) < 0) { 115 u.u_error = EFAULT; 116 return; 117 } 118 } 119 120 dwrap() 121 { 122 register struct a { 123 int d; 124 struct dtype *dtypeb; 125 } *uap = (struct a *)u.u_ap; 126 register struct file *fp; 127 struct dtype adtype; 128 129 fp = getf(uap->d); 130 if (fp == 0) 131 return; 132 if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 133 sizeof (struct dtype)) < 0) { 134 u.u_error = EFAULT; 135 return; 136 } 137 /* DO WRAP */ 138 } 139 140 dselect() 141 { 142 143 } 144 145 dnblock() 146 { 147 register struct a { 148 int d; 149 int how; 150 } *uap = (struct a *)u.u_ap; 151 152 /* XXX */ 153 } 154 155 dsignal() 156 { 157 register struct a { 158 int d; 159 int how; 160 } *uap = (struct a *)u.u_ap; 161 162 /* XXX */ 163 } 164 165 int nselcoll; 166 /* 167 * Select system call. 168 */ 169 oselect() 170 { 171 register struct uap { 172 int nfd; 173 fd_set *rp, *wp; 174 int timo; 175 } *ap = (struct uap *)u.u_ap; 176 fd_set rd, wr; 177 int nfds = 0, readable = 0, writeable = 0; 178 time_t t = time; 179 int s, tsel, ncoll, rem; 180 181 if (ap->nfd > NOFILE) 182 ap->nfd = NOFILE; 183 if (ap->nfd < 0) { 184 u.u_error = EBADF; 185 return; 186 } 187 if (ap->rp && copyin((caddr_t)ap->rp,(caddr_t)&rd,sizeof(fd_set))) 188 return; 189 if (ap->wp && copyin((caddr_t)ap->wp,(caddr_t)&wr,sizeof(fd_set))) 190 return; 191 retry: 192 ncoll = nselcoll; 193 u.u_procp->p_flag |= SSEL; 194 if (ap->rp) 195 readable = selscan(ap->nfd, rd, &nfds, FREAD); 196 if (ap->wp) 197 writeable = selscan(ap->nfd, wr, &nfds, FWRITE); 198 if (u.u_error) 199 goto done; 200 if (readable || writeable) 201 goto done; 202 rem = (ap->timo+999)/1000 - (time - t); 203 if (ap->timo == 0 || rem <= 0) 204 goto done; 205 s = spl6(); 206 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 207 u.u_procp->p_flag &= ~SSEL; 208 splx(s); 209 goto retry; 210 } 211 u.u_procp->p_flag &= ~SSEL; 212 tsel = tsleep((caddr_t)&selwait, PZERO+1, rem); 213 splx(s); 214 switch (tsel) { 215 216 case TS_OK: 217 goto retry; 218 219 case TS_SIG: 220 u.u_error = EINTR; 221 return; 222 223 case TS_TIME: 224 break; 225 } 226 done: 227 rd.fds_bits[0] = readable; 228 wr.fds_bits[0] = writeable; 229 s = sizeof (fd_set); 230 if (s * NBBY > ap->nfd) 231 s = (ap->nfd + NBBY - 1) / NBBY; 232 u.u_r.r_val1 = nfds; 233 if (ap->rp) 234 (void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set)); 235 if (ap->wp) 236 (void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set)); 237 } 238 239 selscan(nfd, fds, nfdp, flag) 240 int nfd; 241 fd_set fds; 242 int *nfdp, flag; 243 { 244 struct file *fp; 245 struct inode *ip; 246 register int bits; 247 int i, able, res = 0; 248 249 bits = fds.fds_bits[0]; 250 while (i = ffs(bits)) { 251 if (i > nfd) 252 break; 253 bits &= ~(1<<(i-1)); 254 fp = u.u_ofile[i-1]; 255 if (fp == NULL) { 256 u.u_error = EBADF; 257 return (0); 258 } 259 if (fp->f_type == DTYPE_SOCKET) 260 able = soselect(fp->f_socket, flag); 261 else { 262 ip = fp->f_inode; 263 switch (ip->i_mode & IFMT) { 264 265 case IFCHR: 266 able = 267 (*cdevsw[major(ip->i_rdev)].d_select) 268 (ip->i_rdev, flag); 269 break; 270 271 case IFBLK: 272 case IFREG: 273 case IFDIR: 274 able = 1; 275 break; 276 } 277 278 } 279 if (able) { 280 res |= (1<<(i-1)); 281 (*nfdp)++; 282 } 283 } 284 return (res); 285 } 286 287 /*ARGSUSED*/ 288 seltrue(dev, flag) 289 dev_t dev; 290 int flag; 291 { 292 293 return (1); 294 } 295 296 selwakeup(p, coll) 297 register struct proc *p; 298 int coll; 299 { 300 int s; 301 302 if (coll) { 303 nselcoll++; 304 wakeup((caddr_t)&selwait); 305 } 306 if (p) { 307 if (p->p_wchan == (caddr_t)&selwait) 308 setrun(p); 309 else { 310 s = spl6(); 311 if (p->p_flag & SSEL) 312 p->p_flag &= ~SSEL; 313 splx(s); 314 } 315 } 316 } 317 318 319 /* 320 * Allocate a user file descriptor. 321 */ 322 ufalloc() 323 { 324 register i; 325 326 for (i=0; i<NOFILE; i++) 327 if (u.u_ofile[i] == NULL) { 328 u.u_r.r_val1 = i; 329 u.u_pofile[i] = 0; 330 return (i); 331 } 332 u.u_error = EMFILE; 333 return (-1); 334 } 335 336 struct file *lastf; 337 /* 338 * Allocate a user file descriptor 339 * and a file structure. 340 * Initialize the descriptor 341 * to point at the file structure. 342 */ 343 struct file * 344 falloc() 345 { 346 register struct file *fp; 347 register i; 348 349 i = ufalloc(); 350 if (i < 0) 351 return (NULL); 352 if (lastf == 0) 353 lastf = file; 354 for (fp = lastf; fp < fileNFILE; fp++) 355 if (fp->f_count == 0) 356 goto slot; 357 for (fp = file; fp < lastf; fp++) 358 if (fp->f_count == 0) 359 goto slot; 360 tablefull("file"); 361 u.u_error = ENFILE; 362 return (NULL); 363 slot: 364 u.u_ofile[i] = fp; 365 fp->f_count++; 366 fp->f_offset = 0; 367 fp->f_inode = 0; 368 lastf = fp + 1; 369 return (fp); 370 } 371 /* 372 * Convert a user supplied file descriptor into a pointer 373 * to a file structure. Only task is to check range of the descriptor. 374 * Critical paths should use the GETF macro, defined in inline.h. 375 */ 376 struct file * 377 getf(f) 378 register int f; 379 { 380 register struct file *fp; 381 382 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 383 u.u_error = EBADF; 384 return (NULL); 385 } 386 return (fp); 387 } 388 389 /* 390 * Internal form of close. 391 * Decrement reference count on 392 * file structure. 393 * Also make sure the pipe protocol 394 * does not constipate. 395 * 396 * Decrement reference count on the inode following 397 * removal to the referencing file structure. 398 * Call device handler on last close. 399 * Nouser indicates that the user isn't available to present 400 * errors to. 401 */ 402 closef(fp, nouser) 403 register struct file *fp; 404 { 405 register struct inode *ip; 406 register struct mount *mp; 407 int flag, mode; 408 dev_t dev; 409 register int (*cfunc)(); 410 411 if (fp == NULL) 412 return; 413 if (fp->f_count > 1) { 414 fp->f_count--; 415 return; 416 } 417 if (fp->f_type == DTYPE_SOCKET) { 418 u.u_error = 0; /* XXX */ 419 soclose(fp->f_socket, nouser); 420 if (nouser == 0 && u.u_error) 421 return; 422 fp->f_socket = 0; 423 fp->f_count = 0; 424 return; 425 } 426 flag = fp->f_flag; 427 ip = fp->f_inode; 428 dev = (dev_t)ip->i_rdev; 429 mode = ip->i_mode & IFMT; 430 ilock(ip); 431 iput(ip); 432 fp->f_count = 0; 433 434 switch (mode) { 435 436 case IFCHR: 437 cfunc = cdevsw[major(dev)].d_close; 438 #ifdef EFS 439 /* 440 * Every close() must call the driver if the 441 * extended file system is being used -- not 442 * just the last close. Pass along the file 443 * pointer for reference later. 444 */ 445 if (major(dev) == efs_major) { 446 (*cfunc)(dev, flag, fp, nouser); 447 return; 448 } 449 #endif 450 break; 451 452 case IFBLK: 453 /* 454 * We don't want to really close the device if it is mounted 455 */ 456 for (mp = mount; mp < &mount[NMOUNT]; mp++) 457 if (mp->m_bufp != NULL && mp->m_dev == dev) 458 return; 459 cfunc = bdevsw[major(dev)].d_close; 460 break; 461 462 default: 463 return; 464 } 465 for (fp = file; fp < fileNFILE; fp++) { 466 if (fp->f_type == DTYPE_SOCKET) /* XXX */ 467 continue; 468 if (fp->f_count && (ip = fp->f_inode) && 469 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 470 return; 471 } 472 if (mode == IFBLK) { 473 /* 474 * On last close of a block device (that isn't mounted) 475 * we must invalidate any in core blocks 476 */ 477 bflush(dev); 478 binval(dev); 479 } 480 (*cfunc)(dev, flag, fp); 481 } 482 483 #ifdef CAD 484 /* 485 * chfile -- change all references to the inode named by 486 * device/inum to the file referred to by fd. 487 * Used by init to remove all references to the device. 488 */ 489 chfile() 490 { 491 register struct file *fp; 492 register struct inode *from; 493 register struct inode *to; 494 off_t offset; 495 dev_t dev; 496 int rw; 497 struct a { 498 int device; /* actually dev_t */ 499 int inum; /* actually ino_t */ 500 int fd; 501 } *uap; 502 503 if (!suser()) { 504 u.u_error = EPERM; 505 return; 506 } 507 uap = (struct a *) u.u_ap; 508 fp = getf(uap->fd); 509 if (fp == NULL) { 510 u.u_error = EBADF; 511 return; 512 } 513 if (fp->f_type == DTYPE_SOCKET) { 514 u.u_error = EINVAL; 515 return; 516 } 517 for (from = &inode[0]; from < &inode[ninode]; from++) 518 if (from->i_number == (ino_t)uap->inum 519 && from->i_dev == (dev_t)uap->device) 520 break; 521 if (from >= &inode[ninode]) { 522 u.u_error = ENXIO; 523 return; 524 } 525 offset = fp->f_offset; 526 to = fp->f_inode; 527 from->i_count++; 528 for (fp = &file[0]; fp < &file[nfile]; fp++) { 529 if (fp->f_count > 0 && fp->f_inode == from) { 530 fp->f_inode = to; 531 to->i_count++; 532 fp->f_offset = offset; 533 rw |= fp->f_flag & FWRITE; 534 iput(from); 535 } 536 } 537 /* 538 * This inode is no longer referenced. 539 * Switch out to the appropriate close 540 * routine, if required 541 */ 542 dev = (dev_t)from->i_un.i_rdev; 543 switch(from->i_mode & IFMT) { 544 545 case IFCHR: 546 (*cdevsw[major(dev)].d_close)(dev, rw); 547 break; 548 549 case IFBLK: 550 (*bdevsw[major(dev)].d_close)(dev, rw); 551 break; 552 553 default: 554 break; 555 } 556 iput(from); 557 } 558 #endif 559