1*8098Sroot /* kern_descrip.c 5.7 82/09/06 */ 27422Sroot 37422Sroot #include "../h/param.h" 47422Sroot #include "../h/systm.h" 57422Sroot #include "../h/dir.h" 67422Sroot #include "../h/user.h" 78029Sroot #include "../h/kernel.h" 87422Sroot #include "../h/inode.h" 97422Sroot #include "../h/proc.h" 107422Sroot #include "../h/conf.h" 117422Sroot #include "../h/file.h" 127422Sroot #include "../h/inline.h" 137422Sroot #include "../h/socket.h" 147422Sroot #include "../h/socketvar.h" 157497Sroot #include "../h/mount.h" 167422Sroot 177497Sroot #include "../h/descrip.h" 187497Sroot 197422Sroot /* 207497Sroot * Descriptor management. 217422Sroot */ 227497Sroot 237497Sroot /* 247497Sroot * TODO: 257497Sroot * getf should be renamed 267497Sroot * ufalloc side effects are gross 277497Sroot */ 287497Sroot 297497Sroot /* 307497Sroot * System calls on descriptors. 317497Sroot */ 328029Sroot getdtablesize() 337497Sroot { 347497Sroot 357497Sroot u.u_r.r_val1 = NOFILE; 367497Sroot } 377497Sroot 38*8098Sroot getdprop() 39*8098Sroot { 40*8098Sroot register struct a { 41*8098Sroot int d; 42*8098Sroot struct dtype *dtypeb; 43*8098Sroot } *uap = (struct a *)u.u_ap; 44*8098Sroot register struct file *fp; 45*8098Sroot struct dtype adtype; 46*8098Sroot 47*8098Sroot fp = getf(uap->d); 48*8098Sroot if (fp == 0) 49*8098Sroot return; 50*8098Sroot adtype.dt_type = 0; /* XXX */ 51*8098Sroot adtype.dt_protocol = 0; /* XXX */ 52*8098Sroot if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 53*8098Sroot sizeof (struct dtype)) < 0) { 54*8098Sroot u.u_error = EFAULT; 55*8098Sroot return; 56*8098Sroot } 57*8098Sroot } 58*8098Sroot 59*8098Sroot getdopt() 60*8098Sroot { 61*8098Sroot 62*8098Sroot } 63*8098Sroot 64*8098Sroot setdopt() 65*8098Sroot { 66*8098Sroot 67*8098Sroot } 68*8098Sroot 697422Sroot dup() 707422Sroot { 717497Sroot register struct a { 727497Sroot int i; 737497Sroot } *uap = (struct a *) u.u_ap; 747696Ssam struct file *fp; 757696Ssam int j; 767497Sroot 777497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 787497Sroot 797497Sroot fp = getf(uap->i); 807497Sroot if (fp == 0) 817497Sroot return; 827497Sroot j = ufalloc(); 837497Sroot if (j < 0) 847497Sroot return; 857696Ssam dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 867497Sroot } 877497Sroot 887497Sroot dup2() 897497Sroot { 907422Sroot register struct a { 917497Sroot int i, j; 927497Sroot } *uap = (struct a *) u.u_ap; 937497Sroot register struct file *fp; 947422Sroot 957497Sroot fp = getf(uap->i); 967497Sroot if (fp == 0) 977422Sroot return; 987497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 997497Sroot u.u_error = EBADF; 1007497Sroot return; 1017422Sroot } 1027497Sroot u.u_r.r_val1 = uap->j; 1037497Sroot if (uap->i == uap->j) 1047497Sroot return; 1057497Sroot if (u.u_ofile[uap->j]) { 1067696Ssam closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); 1077422Sroot if (u.u_error) 1087422Sroot return; 1097497Sroot /* u.u_ofile[uap->j] = 0; */ 1107696Ssam /* u.u_pofile[uap->j] = 0; */ 1117422Sroot } 1127696Ssam dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 1137696Ssam } 1147696Ssam 1157696Ssam dupit(fd, fp, lockflags) 1167696Ssam int fd; 1177696Ssam register struct file *fp; 1187696Ssam register int lockflags; 1197696Ssam { 1207696Ssam 1217696Ssam u.u_ofile[fd] = fp; 1227696Ssam u.u_pofile[fd] = lockflags; 1237497Sroot fp->f_count++; 1247696Ssam if (lockflags&RDLOCK) 1257696Ssam fp->f_inode->i_rdlockc++; 1267696Ssam if (lockflags&WRLOCK) 1277696Ssam fp->f_inode->i_wrlockc++; 1287422Sroot } 1297422Sroot 1307497Sroot close() 1317497Sroot { 1327497Sroot register struct a { 1337497Sroot int i; 1347497Sroot } *uap = (struct a *)u.u_ap; 1357497Sroot register struct file *fp; 1367497Sroot 1377497Sroot fp = getf(uap->i); 1387497Sroot if (fp == 0) 1397497Sroot return; 1407696Ssam closef(fp, 0, u.u_pofile[uap->i]); 1417497Sroot /* WHAT IF u.u_error ? */ 1427696Ssam u.u_ofile[uap->i] = NULL; 1437696Ssam u.u_pofile[uap->i] = 0; 1447497Sroot } 1457497Sroot 1468029Sroot wrap() 1477497Sroot { 1487497Sroot register struct a { 1497497Sroot int d; 1507497Sroot struct dtype *dtypeb; 1517497Sroot } *uap = (struct a *)u.u_ap; 1527497Sroot register struct file *fp; 1537497Sroot struct dtype adtype; 1547497Sroot 1557497Sroot fp = getf(uap->d); 1567497Sroot if (fp == 0) 1577497Sroot return; 1587497Sroot if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 1597497Sroot sizeof (struct dtype)) < 0) { 1607497Sroot u.u_error = EFAULT; 1617497Sroot return; 1627497Sroot } 1637497Sroot /* DO WRAP */ 1647497Sroot } 1657497Sroot 1667422Sroot int nselcoll; 1677422Sroot /* 1687422Sroot * Select system call. 1697422Sroot */ 170*8098Sroot select() 1717422Sroot { 1727422Sroot register struct uap { 173*8098Sroot fd_set *rp, *wp, *ep; 1748029Sroot struct timeval *tv; 1758029Sroot } *uap = (struct uap *)u.u_ap; 1767422Sroot fd_set rd, wr; 1777422Sroot int nfds = 0, readable = 0, writeable = 0; 1788029Sroot struct timeval atv, origin, now; 1797422Sroot int s, tsel, ncoll, rem; 1807422Sroot 1818029Sroot if (uap->tv) { 1828029Sroot if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 1838029Sroot u.u_error = EFAULT; 1848029Sroot return; 1858029Sroot } 1868029Sroot } else 1878029Sroot timerclear(&atv); 1888029Sroot if (uap->rp && copyin((caddr_t)uap->rp,(caddr_t)&rd,sizeof(fd_set))) 1897422Sroot return; 1908029Sroot if (uap->wp && copyin((caddr_t)uap->wp,(caddr_t)&wr,sizeof(fd_set))) 1917422Sroot return; 1927422Sroot retry: 1938029Sroot s = spl7(); now = time; splx(s); 1947422Sroot ncoll = nselcoll; 1957422Sroot u.u_procp->p_flag |= SSEL; 1968029Sroot if (uap->rp) 197*8098Sroot readable = selscan(rd, &nfds, FREAD); 1988029Sroot if (uap->wp) 199*8098Sroot writeable = selscan(wr, &nfds, FWRITE); 2007422Sroot if (u.u_error) 2017422Sroot goto done; 2027422Sroot if (readable || writeable) 2037422Sroot goto done; 2048029Sroot if (!timerisset(&atv)) 2057422Sroot goto done; 2067422Sroot s = spl6(); 2077422Sroot if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 2087422Sroot u.u_procp->p_flag &= ~SSEL; 2097422Sroot splx(s); 2107422Sroot goto retry; 2117422Sroot } 2127422Sroot u.u_procp->p_flag &= ~SSEL; 2138029Sroot tsel = tsleep((caddr_t)&selwait, PZERO+1, &atv); 2147422Sroot splx(s); 2157422Sroot switch (tsel) { 2167422Sroot 2177422Sroot case TS_OK: 2188029Sroot now = time; 2198029Sroot timevalsub(&now, &origin); 2208029Sroot timevalsub(&atv, now); 2218029Sroot if (atv.tv_sec < 0 || atv.tv_usec < 0) 2228029Sroot timerclear(&atv); 2237422Sroot goto retry; 2247422Sroot 2257422Sroot case TS_SIG: 2267422Sroot u.u_error = EINTR; 2277422Sroot return; 2287422Sroot 2297422Sroot case TS_TIME: 2307422Sroot break; 2317422Sroot } 2327422Sroot done: 2337422Sroot rd.fds_bits[0] = readable; 2347422Sroot wr.fds_bits[0] = writeable; 2357422Sroot s = sizeof (fd_set); 2367422Sroot u.u_r.r_val1 = nfds; 2378029Sroot if (uap->rp) 2388029Sroot (void) copyout((caddr_t)&rd, (caddr_t)uap->rp, sizeof(fd_set)); 2398029Sroot if (uap->wp) 2408029Sroot (void) copyout((caddr_t)&wr, (caddr_t)uap->wp, sizeof(fd_set)); 2417422Sroot } 2427422Sroot 243*8098Sroot selscan(fds, nfdp, flag) 2447422Sroot fd_set fds; 2457422Sroot int *nfdp, flag; 2467422Sroot { 2477422Sroot struct file *fp; 2487422Sroot struct inode *ip; 2497422Sroot register int bits; 2507422Sroot int i, able, res = 0; 2517422Sroot 2527422Sroot bits = fds.fds_bits[0]; 2537422Sroot while (i = ffs(bits)) { 2547422Sroot bits &= ~(1<<(i-1)); 2557422Sroot fp = u.u_ofile[i-1]; 2567422Sroot if (fp == NULL) { 2577422Sroot u.u_error = EBADF; 2587422Sroot return (0); 2597422Sroot } 2607497Sroot if (fp->f_type == DTYPE_SOCKET) 2617422Sroot able = soselect(fp->f_socket, flag); 2627422Sroot else { 2637422Sroot ip = fp->f_inode; 2647422Sroot switch (ip->i_mode & IFMT) { 2657422Sroot 2667422Sroot case IFCHR: 2677422Sroot able = 2687422Sroot (*cdevsw[major(ip->i_rdev)].d_select) 2697422Sroot (ip->i_rdev, flag); 2707422Sroot break; 2717422Sroot 2727422Sroot case IFBLK: 2737422Sroot case IFREG: 2747422Sroot case IFDIR: 2757422Sroot able = 1; 2767422Sroot break; 2777422Sroot } 2787497Sroot 2797422Sroot } 2807422Sroot if (able) { 2817422Sroot res |= (1<<(i-1)); 2827422Sroot (*nfdp)++; 2837422Sroot } 2847422Sroot } 2857422Sroot return (res); 2867422Sroot } 2877422Sroot 2887422Sroot /*ARGSUSED*/ 2897422Sroot seltrue(dev, flag) 2907422Sroot dev_t dev; 2917422Sroot int flag; 2927422Sroot { 2937422Sroot 2947422Sroot return (1); 2957422Sroot } 2967422Sroot 2977422Sroot selwakeup(p, coll) 2987422Sroot register struct proc *p; 2997422Sroot int coll; 3007422Sroot { 3017422Sroot int s; 3027422Sroot 3037422Sroot if (coll) { 3047422Sroot nselcoll++; 3057422Sroot wakeup((caddr_t)&selwait); 3067422Sroot } 3077422Sroot if (p) { 3087422Sroot if (p->p_wchan == (caddr_t)&selwait) 3097422Sroot setrun(p); 3107422Sroot else { 3117422Sroot s = spl6(); 3127422Sroot if (p->p_flag & SSEL) 3137422Sroot p->p_flag &= ~SSEL; 3147422Sroot splx(s); 3157422Sroot } 3167422Sroot } 3177422Sroot } 3187422Sroot 3198029Sroot revoke() 3208029Sroot { 3218029Sroot 3228029Sroot /* XXX */ 3238029Sroot } 3248029Sroot 3257422Sroot /* 3267497Sroot * Allocate a user file descriptor. 3277422Sroot */ 3287497Sroot ufalloc() 3297422Sroot { 3307497Sroot register i; 3317497Sroot 3327497Sroot for (i=0; i<NOFILE; i++) 3337497Sroot if (u.u_ofile[i] == NULL) { 3347497Sroot u.u_r.r_val1 = i; 3357497Sroot u.u_pofile[i] = 0; 3367497Sroot return (i); 3377497Sroot } 3387497Sroot u.u_error = EMFILE; 3397497Sroot return (-1); 3407497Sroot } 3417497Sroot 3427497Sroot struct file *lastf; 3437497Sroot /* 3447497Sroot * Allocate a user file descriptor 3457497Sroot * and a file structure. 3467497Sroot * Initialize the descriptor 3477497Sroot * to point at the file structure. 3487497Sroot */ 3497497Sroot struct file * 3507497Sroot falloc() 3517497Sroot { 3527422Sroot register struct file *fp; 3537497Sroot register i; 3547422Sroot 3557497Sroot i = ufalloc(); 3567497Sroot if (i < 0) 3577497Sroot return (NULL); 3587497Sroot if (lastf == 0) 3597497Sroot lastf = file; 3607497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3617497Sroot if (fp->f_count == 0) 3627497Sroot goto slot; 3637497Sroot for (fp = file; fp < lastf; fp++) 3647497Sroot if (fp->f_count == 0) 3657497Sroot goto slot; 3667497Sroot tablefull("file"); 3677497Sroot u.u_error = ENFILE; 3687497Sroot return (NULL); 3697497Sroot slot: 3707497Sroot u.u_ofile[i] = fp; 3717497Sroot fp->f_count++; 3727497Sroot fp->f_offset = 0; 3737497Sroot fp->f_inode = 0; 3747497Sroot lastf = fp + 1; 3757497Sroot return (fp); 3767497Sroot } 3777497Sroot /* 3787497Sroot * Convert a user supplied file descriptor into a pointer 3797497Sroot * to a file structure. Only task is to check range of the descriptor. 3807497Sroot * Critical paths should use the GETF macro, defined in inline.h. 3817497Sroot */ 3827497Sroot struct file * 3837497Sroot getf(f) 3847497Sroot register int f; 3857497Sroot { 3867497Sroot register struct file *fp; 3877497Sroot 3887497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 3897497Sroot u.u_error = EBADF; 3907497Sroot return (NULL); 3917497Sroot } 3927497Sroot return (fp); 3937497Sroot } 3947497Sroot 3957497Sroot /* 3967497Sroot * Internal form of close. 3977497Sroot * Decrement reference count on 3987497Sroot * file structure. 3997497Sroot * Also make sure the pipe protocol 4007497Sroot * does not constipate. 4017497Sroot * 4027497Sroot * Decrement reference count on the inode following 4037497Sroot * removal to the referencing file structure. 4047497Sroot * Call device handler on last close. 4057497Sroot * Nouser indicates that the user isn't available to present 4067497Sroot * errors to. 4077696Ssam * 4087696Ssam * Handling locking at this level is RIDICULOUS. 4097497Sroot */ 4107696Ssam closef(fp, nouser, flags) 4117497Sroot register struct file *fp; 4127696Ssam int nouser, flags; 4137497Sroot { 4147497Sroot register struct inode *ip; 4157497Sroot register struct mount *mp; 4167497Sroot int flag, mode; 4177497Sroot dev_t dev; 4187497Sroot register int (*cfunc)(); 4197497Sroot 4207422Sroot if (fp == NULL) 4217422Sroot return; 4227497Sroot if (fp->f_count > 1) { 4237497Sroot fp->f_count--; 4247422Sroot return; 4257422Sroot } 4267497Sroot if (fp->f_type == DTYPE_SOCKET) { 4277497Sroot u.u_error = 0; /* XXX */ 4287497Sroot soclose(fp->f_socket, nouser); 4297497Sroot if (nouser == 0 && u.u_error) 4307497Sroot return; 4317497Sroot fp->f_socket = 0; 4327497Sroot fp->f_count = 0; 4337497Sroot return; 4347497Sroot } 4357497Sroot flag = fp->f_flag; 4367497Sroot ip = fp->f_inode; 4377497Sroot dev = (dev_t)ip->i_rdev; 4387497Sroot mode = ip->i_mode & IFMT; 4397696Ssam flags &= RDLOCK|WRLOCK; /* conservative */ 4407696Ssam if (flags) 4417696Ssam funlocki(ip, flags); 4427497Sroot ilock(ip); 4437497Sroot iput(ip); 4447497Sroot fp->f_count = 0; 4457497Sroot 4467497Sroot switch (mode) { 4477497Sroot 4487497Sroot case IFCHR: 4497497Sroot cfunc = cdevsw[major(dev)].d_close; 4507497Sroot break; 4517497Sroot 4527497Sroot case IFBLK: 4537497Sroot /* 4547497Sroot * We don't want to really close the device if it is mounted 4557497Sroot */ 4567497Sroot for (mp = mount; mp < &mount[NMOUNT]; mp++) 4577497Sroot if (mp->m_bufp != NULL && mp->m_dev == dev) 4587497Sroot return; 4597497Sroot cfunc = bdevsw[major(dev)].d_close; 4607497Sroot break; 4617497Sroot 4627497Sroot default: 4637497Sroot return; 4647497Sroot } 4657497Sroot for (fp = file; fp < fileNFILE; fp++) { 4667497Sroot if (fp->f_type == DTYPE_SOCKET) /* XXX */ 4677497Sroot continue; 4687497Sroot if (fp->f_count && (ip = fp->f_inode) && 4697497Sroot ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 4707497Sroot return; 4717497Sroot } 4727497Sroot if (mode == IFBLK) { 4737497Sroot /* 4747497Sroot * On last close of a block device (that isn't mounted) 4757497Sroot * we must invalidate any in core blocks 4767497Sroot */ 4777497Sroot bflush(dev); 4787497Sroot binval(dev); 4797497Sroot } 4807497Sroot (*cfunc)(dev, flag, fp); 4817422Sroot } 482