1*7497Sroot /* kern_descrip.c 5.2 82/07/24 */ 27422Sroot 37422Sroot #include "../h/param.h" 47422Sroot #include "../h/systm.h" 57422Sroot #include "../h/dir.h" 67422Sroot #include "../h/user.h" 77422Sroot #include "../h/inode.h" 87422Sroot #include "../h/proc.h" 97422Sroot #include "../h/conf.h" 107422Sroot #include "../h/file.h" 117422Sroot #include "../h/inline.h" 127422Sroot #include "../h/socket.h" 137422Sroot #include "../h/socketvar.h" 14*7497Sroot #include "../h/mount.h" 157422Sroot 16*7497Sroot #include "../h/descrip.h" 17*7497Sroot 187422Sroot /* 19*7497Sroot * Descriptor management. 207422Sroot */ 21*7497Sroot 22*7497Sroot /* 23*7497Sroot * TODO: 24*7497Sroot * getf should be renamed 25*7497Sroot * ufalloc side effects are gross 26*7497Sroot */ 27*7497Sroot 28*7497Sroot /* 29*7497Sroot * System calls on descriptors. 30*7497Sroot */ 31*7497Sroot dstd() 32*7497Sroot { 33*7497Sroot 34*7497Sroot u.u_r.r_val1 = NOFILE; 35*7497Sroot } 36*7497Sroot 377422Sroot dup() 387422Sroot { 39*7497Sroot register struct a { 40*7497Sroot int i; 41*7497Sroot } *uap = (struct a *) u.u_ap; 427422Sroot register struct file *fp; 43*7497Sroot register int j; 44*7497Sroot 45*7497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 46*7497Sroot 47*7497Sroot fp = getf(uap->i); 48*7497Sroot if (fp == 0) 49*7497Sroot return; 50*7497Sroot j = ufalloc(); 51*7497Sroot if (j < 0) 52*7497Sroot return; 53*7497Sroot u.u_ofile[j] = fp; 54*7497Sroot fp->f_count++; 55*7497Sroot } 56*7497Sroot 57*7497Sroot dup2() 58*7497Sroot { 597422Sroot register struct a { 60*7497Sroot int i, j; 61*7497Sroot } *uap = (struct a *) u.u_ap; 62*7497Sroot register struct file *fp; 637422Sroot 64*7497Sroot fp = getf(uap->i); 65*7497Sroot if (fp == 0) 667422Sroot return; 67*7497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 68*7497Sroot u.u_error = EBADF; 69*7497Sroot return; 707422Sroot } 71*7497Sroot u.u_r.r_val1 = uap->j; 72*7497Sroot if (uap->i == uap->j) 73*7497Sroot return; 74*7497Sroot if (u.u_ofile[uap->j]) { 75*7497Sroot closef(u.u_ofile[uap->j], 0); 767422Sroot if (u.u_error) 777422Sroot return; 78*7497Sroot /* u.u_ofile[uap->j] = 0; */ 797422Sroot } 80*7497Sroot u.u_ofile[uap->j] = fp; 81*7497Sroot fp->f_count++; 827422Sroot } 837422Sroot 84*7497Sroot close() 85*7497Sroot { 86*7497Sroot register struct a { 87*7497Sroot int i; 88*7497Sroot } *uap = (struct a *)u.u_ap; 89*7497Sroot register struct file *fp; 90*7497Sroot 91*7497Sroot fp = getf(uap->i); 92*7497Sroot if (fp == 0) 93*7497Sroot return; 94*7497Sroot u.u_ofile[uap->i] = 0; 95*7497Sroot closef(fp, 0); 96*7497Sroot /* WHAT IF u.u_error ? */ 97*7497Sroot } 98*7497Sroot 99*7497Sroot dtype() 100*7497Sroot { 101*7497Sroot register struct a { 102*7497Sroot int d; 103*7497Sroot struct dtype *dtypeb; 104*7497Sroot } *uap = (struct a *)u.u_ap; 105*7497Sroot register struct file *fp; 106*7497Sroot struct dtype adtype; 107*7497Sroot 108*7497Sroot fp = getf(uap->d); 109*7497Sroot if (fp == 0) 110*7497Sroot return; 111*7497Sroot adtype.dt_type = 0; /* XXX */ 112*7497Sroot adtype.dt_protocol = 0; /* XXX */ 113*7497Sroot if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 114*7497Sroot sizeof (struct dtype)) < 0) { 115*7497Sroot u.u_error = EFAULT; 116*7497Sroot return; 117*7497Sroot } 118*7497Sroot } 119*7497Sroot 120*7497Sroot dwrap() 121*7497Sroot { 122*7497Sroot register struct a { 123*7497Sroot int d; 124*7497Sroot struct dtype *dtypeb; 125*7497Sroot } *uap = (struct a *)u.u_ap; 126*7497Sroot register struct file *fp; 127*7497Sroot struct dtype adtype; 128*7497Sroot 129*7497Sroot fp = getf(uap->d); 130*7497Sroot if (fp == 0) 131*7497Sroot return; 132*7497Sroot if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 133*7497Sroot sizeof (struct dtype)) < 0) { 134*7497Sroot u.u_error = EFAULT; 135*7497Sroot return; 136*7497Sroot } 137*7497Sroot /* DO WRAP */ 138*7497Sroot } 139*7497Sroot 140*7497Sroot dselect() 141*7497Sroot { 142*7497Sroot 143*7497Sroot } 144*7497Sroot 145*7497Sroot dnblock() 146*7497Sroot { 147*7497Sroot register struct a { 148*7497Sroot int d; 149*7497Sroot int how; 150*7497Sroot } *uap = (struct a *)u.u_ap; 151*7497Sroot 152*7497Sroot /* XXX */ 153*7497Sroot } 154*7497Sroot 155*7497Sroot dsignal() 156*7497Sroot { 157*7497Sroot register struct a { 158*7497Sroot int d; 159*7497Sroot int how; 160*7497Sroot } *uap = (struct a *)u.u_ap; 161*7497Sroot 162*7497Sroot /* XXX */ 163*7497Sroot } 164*7497Sroot 1657422Sroot int nselcoll; 1667422Sroot /* 1677422Sroot * Select system call. 1687422Sroot */ 169*7497Sroot oselect() 1707422Sroot { 1717422Sroot register struct uap { 1727422Sroot int nfd; 1737422Sroot fd_set *rp, *wp; 1747422Sroot int timo; 1757422Sroot } *ap = (struct uap *)u.u_ap; 1767422Sroot fd_set rd, wr; 1777422Sroot int nfds = 0, readable = 0, writeable = 0; 1787422Sroot time_t t = time; 1797422Sroot int s, tsel, ncoll, rem; 1807422Sroot 1817422Sroot if (ap->nfd > NOFILE) 1827422Sroot ap->nfd = NOFILE; 1837422Sroot if (ap->nfd < 0) { 1847422Sroot u.u_error = EBADF; 1857422Sroot return; 1867422Sroot } 1877422Sroot if (ap->rp && copyin((caddr_t)ap->rp,(caddr_t)&rd,sizeof(fd_set))) 1887422Sroot return; 1897422Sroot if (ap->wp && copyin((caddr_t)ap->wp,(caddr_t)&wr,sizeof(fd_set))) 1907422Sroot return; 1917422Sroot retry: 1927422Sroot ncoll = nselcoll; 1937422Sroot u.u_procp->p_flag |= SSEL; 1947422Sroot if (ap->rp) 1957422Sroot readable = selscan(ap->nfd, rd, &nfds, FREAD); 1967422Sroot if (ap->wp) 1977422Sroot writeable = selscan(ap->nfd, wr, &nfds, FWRITE); 1987422Sroot if (u.u_error) 1997422Sroot goto done; 2007422Sroot if (readable || writeable) 2017422Sroot goto done; 2027422Sroot rem = (ap->timo+999)/1000 - (time - t); 2037422Sroot if (ap->timo == 0 || rem <= 0) 2047422Sroot goto done; 2057422Sroot s = spl6(); 2067422Sroot if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 2077422Sroot u.u_procp->p_flag &= ~SSEL; 2087422Sroot splx(s); 2097422Sroot goto retry; 2107422Sroot } 2117422Sroot u.u_procp->p_flag &= ~SSEL; 2127422Sroot tsel = tsleep((caddr_t)&selwait, PZERO+1, rem); 2137422Sroot splx(s); 2147422Sroot switch (tsel) { 2157422Sroot 2167422Sroot case TS_OK: 2177422Sroot goto retry; 2187422Sroot 2197422Sroot case TS_SIG: 2207422Sroot u.u_error = EINTR; 2217422Sroot return; 2227422Sroot 2237422Sroot case TS_TIME: 2247422Sroot break; 2257422Sroot } 2267422Sroot done: 2277422Sroot rd.fds_bits[0] = readable; 2287422Sroot wr.fds_bits[0] = writeable; 2297422Sroot s = sizeof (fd_set); 2307422Sroot if (s * NBBY > ap->nfd) 2317422Sroot s = (ap->nfd + NBBY - 1) / NBBY; 2327422Sroot u.u_r.r_val1 = nfds; 2337422Sroot if (ap->rp) 2347422Sroot (void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set)); 2357422Sroot if (ap->wp) 2367422Sroot (void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set)); 2377422Sroot } 2387422Sroot 2397422Sroot selscan(nfd, fds, nfdp, flag) 2407422Sroot int nfd; 2417422Sroot fd_set fds; 2427422Sroot int *nfdp, flag; 2437422Sroot { 2447422Sroot struct file *fp; 2457422Sroot struct inode *ip; 2467422Sroot register int bits; 2477422Sroot int i, able, res = 0; 2487422Sroot 2497422Sroot bits = fds.fds_bits[0]; 2507422Sroot while (i = ffs(bits)) { 2517422Sroot if (i > nfd) 2527422Sroot break; 2537422Sroot bits &= ~(1<<(i-1)); 2547422Sroot fp = u.u_ofile[i-1]; 2557422Sroot if (fp == NULL) { 2567422Sroot u.u_error = EBADF; 2577422Sroot return (0); 2587422Sroot } 259*7497Sroot if (fp->f_type == DTYPE_SOCKET) 2607422Sroot able = soselect(fp->f_socket, flag); 2617422Sroot else { 2627422Sroot ip = fp->f_inode; 2637422Sroot switch (ip->i_mode & IFMT) { 2647422Sroot 2657422Sroot case IFCHR: 2667422Sroot able = 2677422Sroot (*cdevsw[major(ip->i_rdev)].d_select) 2687422Sroot (ip->i_rdev, flag); 2697422Sroot break; 2707422Sroot 2717422Sroot case IFBLK: 2727422Sroot case IFREG: 2737422Sroot case IFDIR: 2747422Sroot able = 1; 2757422Sroot break; 2767422Sroot } 277*7497Sroot 2787422Sroot } 2797422Sroot if (able) { 2807422Sroot res |= (1<<(i-1)); 2817422Sroot (*nfdp)++; 2827422Sroot } 2837422Sroot } 2847422Sroot return (res); 2857422Sroot } 2867422Sroot 2877422Sroot /*ARGSUSED*/ 2887422Sroot seltrue(dev, flag) 2897422Sroot dev_t dev; 2907422Sroot int flag; 2917422Sroot { 2927422Sroot 2937422Sroot return (1); 2947422Sroot } 2957422Sroot 2967422Sroot selwakeup(p, coll) 2977422Sroot register struct proc *p; 2987422Sroot int coll; 2997422Sroot { 3007422Sroot int s; 3017422Sroot 3027422Sroot if (coll) { 3037422Sroot nselcoll++; 3047422Sroot wakeup((caddr_t)&selwait); 3057422Sroot } 3067422Sroot if (p) { 3077422Sroot if (p->p_wchan == (caddr_t)&selwait) 3087422Sroot setrun(p); 3097422Sroot else { 3107422Sroot s = spl6(); 3117422Sroot if (p->p_flag & SSEL) 3127422Sroot p->p_flag &= ~SSEL; 3137422Sroot splx(s); 3147422Sroot } 3157422Sroot } 3167422Sroot } 3177422Sroot 318*7497Sroot 3197422Sroot /* 320*7497Sroot * Allocate a user file descriptor. 3217422Sroot */ 322*7497Sroot ufalloc() 3237422Sroot { 324*7497Sroot register i; 325*7497Sroot 326*7497Sroot for (i=0; i<NOFILE; i++) 327*7497Sroot if (u.u_ofile[i] == NULL) { 328*7497Sroot u.u_r.r_val1 = i; 329*7497Sroot u.u_pofile[i] = 0; 330*7497Sroot return (i); 331*7497Sroot } 332*7497Sroot u.u_error = EMFILE; 333*7497Sroot return (-1); 334*7497Sroot } 335*7497Sroot 336*7497Sroot struct file *lastf; 337*7497Sroot /* 338*7497Sroot * Allocate a user file descriptor 339*7497Sroot * and a file structure. 340*7497Sroot * Initialize the descriptor 341*7497Sroot * to point at the file structure. 342*7497Sroot */ 343*7497Sroot struct file * 344*7497Sroot falloc() 345*7497Sroot { 3467422Sroot register struct file *fp; 347*7497Sroot register i; 3487422Sroot 349*7497Sroot i = ufalloc(); 350*7497Sroot if (i < 0) 351*7497Sroot return (NULL); 352*7497Sroot if (lastf == 0) 353*7497Sroot lastf = file; 354*7497Sroot for (fp = lastf; fp < fileNFILE; fp++) 355*7497Sroot if (fp->f_count == 0) 356*7497Sroot goto slot; 357*7497Sroot for (fp = file; fp < lastf; fp++) 358*7497Sroot if (fp->f_count == 0) 359*7497Sroot goto slot; 360*7497Sroot tablefull("file"); 361*7497Sroot u.u_error = ENFILE; 362*7497Sroot return (NULL); 363*7497Sroot slot: 364*7497Sroot u.u_ofile[i] = fp; 365*7497Sroot fp->f_count++; 366*7497Sroot fp->f_offset = 0; 367*7497Sroot fp->f_inode = 0; 368*7497Sroot lastf = fp + 1; 369*7497Sroot return (fp); 370*7497Sroot } 371*7497Sroot /* 372*7497Sroot * Convert a user supplied file descriptor into a pointer 373*7497Sroot * to a file structure. Only task is to check range of the descriptor. 374*7497Sroot * Critical paths should use the GETF macro, defined in inline.h. 375*7497Sroot */ 376*7497Sroot struct file * 377*7497Sroot getf(f) 378*7497Sroot register int f; 379*7497Sroot { 380*7497Sroot register struct file *fp; 381*7497Sroot 382*7497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 383*7497Sroot u.u_error = EBADF; 384*7497Sroot return (NULL); 385*7497Sroot } 386*7497Sroot return (fp); 387*7497Sroot } 388*7497Sroot 389*7497Sroot /* 390*7497Sroot * Internal form of close. 391*7497Sroot * Decrement reference count on 392*7497Sroot * file structure. 393*7497Sroot * Also make sure the pipe protocol 394*7497Sroot * does not constipate. 395*7497Sroot * 396*7497Sroot * Decrement reference count on the inode following 397*7497Sroot * removal to the referencing file structure. 398*7497Sroot * Call device handler on last close. 399*7497Sroot * Nouser indicates that the user isn't available to present 400*7497Sroot * errors to. 401*7497Sroot */ 402*7497Sroot closef(fp, nouser) 403*7497Sroot register struct file *fp; 404*7497Sroot { 405*7497Sroot register struct inode *ip; 406*7497Sroot register struct mount *mp; 407*7497Sroot int flag, mode; 408*7497Sroot dev_t dev; 409*7497Sroot register int (*cfunc)(); 410*7497Sroot 4117422Sroot if (fp == NULL) 4127422Sroot return; 413*7497Sroot if (fp->f_count > 1) { 414*7497Sroot fp->f_count--; 4157422Sroot return; 4167422Sroot } 417*7497Sroot if (fp->f_type == DTYPE_SOCKET) { 418*7497Sroot u.u_error = 0; /* XXX */ 419*7497Sroot soclose(fp->f_socket, nouser); 420*7497Sroot if (nouser == 0 && u.u_error) 421*7497Sroot return; 422*7497Sroot fp->f_socket = 0; 423*7497Sroot fp->f_count = 0; 424*7497Sroot return; 425*7497Sroot } 426*7497Sroot flag = fp->f_flag; 427*7497Sroot ip = fp->f_inode; 428*7497Sroot dev = (dev_t)ip->i_rdev; 429*7497Sroot mode = ip->i_mode & IFMT; 430*7497Sroot ilock(ip); 431*7497Sroot iput(ip); 432*7497Sroot fp->f_count = 0; 433*7497Sroot 434*7497Sroot switch (mode) { 435*7497Sroot 436*7497Sroot case IFCHR: 437*7497Sroot cfunc = cdevsw[major(dev)].d_close; 438*7497Sroot #ifdef EFS 439*7497Sroot /* 440*7497Sroot * Every close() must call the driver if the 441*7497Sroot * extended file system is being used -- not 442*7497Sroot * just the last close. Pass along the file 443*7497Sroot * pointer for reference later. 444*7497Sroot */ 445*7497Sroot if (major(dev) == efs_major) { 446*7497Sroot (*cfunc)(dev, flag, fp, nouser); 447*7497Sroot return; 448*7497Sroot } 449*7497Sroot #endif 450*7497Sroot break; 451*7497Sroot 452*7497Sroot case IFBLK: 453*7497Sroot /* 454*7497Sroot * We don't want to really close the device if it is mounted 455*7497Sroot */ 456*7497Sroot for (mp = mount; mp < &mount[NMOUNT]; mp++) 457*7497Sroot if (mp->m_bufp != NULL && mp->m_dev == dev) 458*7497Sroot return; 459*7497Sroot cfunc = bdevsw[major(dev)].d_close; 460*7497Sroot break; 461*7497Sroot 462*7497Sroot default: 463*7497Sroot return; 464*7497Sroot } 465*7497Sroot for (fp = file; fp < fileNFILE; fp++) { 466*7497Sroot if (fp->f_type == DTYPE_SOCKET) /* XXX */ 467*7497Sroot continue; 468*7497Sroot if (fp->f_count && (ip = fp->f_inode) && 469*7497Sroot ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 470*7497Sroot return; 471*7497Sroot } 472*7497Sroot if (mode == IFBLK) { 473*7497Sroot /* 474*7497Sroot * On last close of a block device (that isn't mounted) 475*7497Sroot * we must invalidate any in core blocks 476*7497Sroot */ 477*7497Sroot bflush(dev); 478*7497Sroot binval(dev); 479*7497Sroot } 480*7497Sroot (*cfunc)(dev, flag, fp); 4817422Sroot } 482*7497Sroot 483*7497Sroot #ifdef CAD 484*7497Sroot /* 485*7497Sroot * chfile -- change all references to the inode named by 486*7497Sroot * device/inum to the file referred to by fd. 487*7497Sroot * Used by init to remove all references to the device. 488*7497Sroot */ 489*7497Sroot chfile() 490*7497Sroot { 491*7497Sroot register struct file *fp; 492*7497Sroot register struct inode *from; 493*7497Sroot register struct inode *to; 494*7497Sroot off_t offset; 495*7497Sroot dev_t dev; 496*7497Sroot int rw; 497*7497Sroot struct a { 498*7497Sroot int device; /* actually dev_t */ 499*7497Sroot int inum; /* actually ino_t */ 500*7497Sroot int fd; 501*7497Sroot } *uap; 502*7497Sroot 503*7497Sroot if (!suser()) { 504*7497Sroot u.u_error = EPERM; 505*7497Sroot return; 506*7497Sroot } 507*7497Sroot uap = (struct a *) u.u_ap; 508*7497Sroot fp = getf(uap->fd); 509*7497Sroot if (fp == NULL) { 510*7497Sroot u.u_error = EBADF; 511*7497Sroot return; 512*7497Sroot } 513*7497Sroot if (fp->f_type == DTYPE_SOCKET) { 514*7497Sroot u.u_error = EINVAL; 515*7497Sroot return; 516*7497Sroot } 517*7497Sroot for (from = &inode[0]; from < &inode[ninode]; from++) 518*7497Sroot if (from->i_number == (ino_t)uap->inum 519*7497Sroot && from->i_dev == (dev_t)uap->device) 520*7497Sroot break; 521*7497Sroot if (from >= &inode[ninode]) { 522*7497Sroot u.u_error = ENXIO; 523*7497Sroot return; 524*7497Sroot } 525*7497Sroot offset = fp->f_offset; 526*7497Sroot to = fp->f_inode; 527*7497Sroot from->i_count++; 528*7497Sroot for (fp = &file[0]; fp < &file[nfile]; fp++) { 529*7497Sroot if (fp->f_count > 0 && fp->f_inode == from) { 530*7497Sroot fp->f_inode = to; 531*7497Sroot to->i_count++; 532*7497Sroot fp->f_offset = offset; 533*7497Sroot rw |= fp->f_flag & FWRITE; 534*7497Sroot iput(from); 535*7497Sroot } 536*7497Sroot } 537*7497Sroot /* 538*7497Sroot * This inode is no longer referenced. 539*7497Sroot * Switch out to the appropriate close 540*7497Sroot * routine, if required 541*7497Sroot */ 542*7497Sroot dev = (dev_t)from->i_un.i_rdev; 543*7497Sroot switch(from->i_mode & IFMT) { 544*7497Sroot 545*7497Sroot case IFCHR: 546*7497Sroot (*cdevsw[major(dev)].d_close)(dev, rw); 547*7497Sroot break; 548*7497Sroot 549*7497Sroot case IFBLK: 550*7497Sroot (*bdevsw[major(dev)].d_close)(dev, rw); 551*7497Sroot break; 552*7497Sroot 553*7497Sroot default: 554*7497Sroot break; 555*7497Sroot } 556*7497Sroot iput(from); 557*7497Sroot } 558*7497Sroot #endif 559