1*8119Sroot /* kern_descrip.c 5.9 82/09/08 */ 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 388098Sroot getdprop() 398098Sroot { 408098Sroot register struct a { 418098Sroot int d; 428098Sroot struct dtype *dtypeb; 438098Sroot } *uap = (struct a *)u.u_ap; 448098Sroot register struct file *fp; 458098Sroot struct dtype adtype; 468098Sroot 478098Sroot fp = getf(uap->d); 488098Sroot if (fp == 0) 498098Sroot return; 508098Sroot adtype.dt_type = 0; /* XXX */ 518098Sroot adtype.dt_protocol = 0; /* XXX */ 528098Sroot if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 538098Sroot sizeof (struct dtype)) < 0) { 548098Sroot u.u_error = EFAULT; 558098Sroot return; 568098Sroot } 578098Sroot } 588098Sroot 598098Sroot getdopt() 608098Sroot { 618098Sroot 628098Sroot } 638098Sroot 648098Sroot setdopt() 658098Sroot { 668098Sroot 678098Sroot } 688098Sroot 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 1668115Sroot int unselect(); 1677422Sroot int nselcoll; 1687422Sroot /* 1697422Sroot * Select system call. 1707422Sroot */ 1718098Sroot select() 1727422Sroot { 1737422Sroot register struct uap { 1748115Sroot long *ibits; 1758115Sroot long *obits; 1768029Sroot struct timeval *tv; 1778029Sroot } *uap = (struct uap *)u.u_ap; 1788115Sroot int ibits[3], obits[3]; 1798115Sroot struct timeval atv; 1807422Sroot int s, tsel, ncoll, rem; 1818115Sroot label_t lqsave; 1827422Sroot 1838029Sroot if (uap->tv) { 1848029Sroot if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 1858029Sroot u.u_error = EFAULT; 1868029Sroot return; 1878029Sroot } 1888115Sroot if (itimerfix(&atv)) { 1898115Sroot u.u_error = EINVAL; 1908115Sroot return; 1918115Sroot } 1928115Sroot s = spl7(); timevaladd(&atv, &time); splx(s); 1938115Sroot } 1948115Sroot if (copyin((caddr_t)uap->ibits, (caddr_t)ibits, sizeof (ibits))) { 1958115Sroot u.u_error = EFAULT; 1967422Sroot return; 1978115Sroot } 1987422Sroot retry: 1997422Sroot ncoll = nselcoll; 2007422Sroot u.u_procp->p_flag |= SSEL; 2018115Sroot u.u_r.r_val1 = selscan(ibits, obits); 2027422Sroot if (u.u_error) 2038115Sroot return; 2048115Sroot if (u.u_r.r_val1) 2057422Sroot goto done; 2068115Sroot s = spl6(); 2078115Sroot if (uap->tv && timercmp(&atv, &time, >=)) { 2088115Sroot splx(s); 2097422Sroot goto done; 2108115Sroot } 2117422Sroot if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 2127422Sroot u.u_procp->p_flag &= ~SSEL; 2137422Sroot splx(s); 2147422Sroot goto retry; 2157422Sroot } 2167422Sroot u.u_procp->p_flag &= ~SSEL; 2178115Sroot if (uap->tv) { 2188115Sroot lqsave = u.u_qsave; 2198115Sroot if (setjmp(&u.u_qsave)) { 2208115Sroot untimeout(unselect, u.u_procp); 2218115Sroot u.u_error = EINTR; 2228115Sroot splx(s); 2238115Sroot return; 2248115Sroot } 2258115Sroot timeout(unselect, u.u_procp, hzto(&atv)); 2268115Sroot } 2278115Sroot sleep((caddr_t)&selwait, PZERO+1); 2288115Sroot if (uap->tv) { 2298115Sroot u.u_qsave = lqsave; 2308115Sroot untimeout(unselect, u.u_procp); 2318115Sroot } 2327422Sroot splx(s); 2338115Sroot goto retry; 2348115Sroot done: 2358115Sroot if (copyout((caddr_t)obits, (caddr_t)uap->obits, sizeof (obits))) { 2368115Sroot u.u_error = EFAULT; 2378115Sroot return; 2388115Sroot } 2398115Sroot } 2407422Sroot 2418115Sroot unselect(p) 2428115Sroot register struct proc *p; 2438115Sroot { 2448115Sroot register int s = spl6(); 2457422Sroot 2468115Sroot switch (p->p_stat) { 2477422Sroot 2488115Sroot case SSLEEP: 2498115Sroot setrun(p); 2507422Sroot break; 2518115Sroot 2528115Sroot case SSTOP: 2538115Sroot unsleep(p); 2548115Sroot break; 2557422Sroot } 2568115Sroot splx(s); 2577422Sroot } 2587422Sroot 2598115Sroot selscan(ibits, obits) 2608115Sroot int *ibits, *obits; 2617422Sroot { 2628115Sroot register int which, bits, i; 2638115Sroot int flag; 2647422Sroot struct file *fp; 2658115Sroot int able; 2667422Sroot struct inode *ip; 2678115Sroot int n = 0; 2687422Sroot 2698115Sroot for (which = 0; which < 3; which++) { 2708115Sroot bits = ibits[which]; 2718115Sroot obits[which] = 0; 2728115Sroot switch (which) { 2737422Sroot 2748115Sroot case 0: 2758115Sroot flag = FREAD; break; 2768115Sroot 2778115Sroot case 1: 2788115Sroot flag = FWRITE; break; 2798115Sroot 2808115Sroot case 2: 2818115Sroot flag = 0; break; 2828115Sroot } 2838115Sroot while (i = ffs(bits)) { 2848115Sroot bits &= ~(1<<(i-1)); 2858115Sroot fp = u.u_ofile[i-1]; 2868115Sroot if (fp == NULL) { 2878115Sroot u.u_error = EBADF; 2887422Sroot break; 2897422Sroot } 2908115Sroot if (fp->f_type == DTYPE_SOCKET) 2918115Sroot able = soselect(fp->f_socket, flag); 2928115Sroot else { 2938115Sroot ip = fp->f_inode; 2948115Sroot switch (ip->i_mode & IFMT) { 2957497Sroot 2968115Sroot case IFCHR: 2978115Sroot able = 2988115Sroot (*cdevsw[major(ip->i_rdev)].d_select) 2998115Sroot (ip->i_rdev, flag); 3008115Sroot break; 3018115Sroot 3028115Sroot case IFBLK: 3038115Sroot case IFREG: 3048115Sroot case IFDIR: 3058115Sroot able = 1; 3068115Sroot break; 3078115Sroot } 3088115Sroot 3098115Sroot } 3108115Sroot if (able) { 3118115Sroot obits[which] |= (1<<(i-1)); 3128115Sroot n++; 3138115Sroot } 3147422Sroot } 3157422Sroot } 3168115Sroot return (n); 3177422Sroot } 3187422Sroot 3197422Sroot /*ARGSUSED*/ 3207422Sroot seltrue(dev, flag) 3217422Sroot dev_t dev; 3227422Sroot int flag; 3237422Sroot { 3247422Sroot 3257422Sroot return (1); 3267422Sroot } 3277422Sroot 3287422Sroot selwakeup(p, coll) 3297422Sroot register struct proc *p; 3307422Sroot int coll; 3317422Sroot { 3327422Sroot int s; 3337422Sroot 3347422Sroot if (coll) { 3357422Sroot nselcoll++; 3367422Sroot wakeup((caddr_t)&selwait); 3377422Sroot } 3387422Sroot if (p) { 3397422Sroot if (p->p_wchan == (caddr_t)&selwait) 3407422Sroot setrun(p); 3417422Sroot else { 3427422Sroot s = spl6(); 3437422Sroot if (p->p_flag & SSEL) 3447422Sroot p->p_flag &= ~SSEL; 3457422Sroot splx(s); 3467422Sroot } 3477422Sroot } 3487422Sroot } 3497422Sroot 3508029Sroot revoke() 3518029Sroot { 3528029Sroot 3538029Sroot /* XXX */ 3548029Sroot } 3558029Sroot 3567422Sroot /* 3577497Sroot * Allocate a user file descriptor. 3587422Sroot */ 3597497Sroot ufalloc() 3607422Sroot { 3617497Sroot register i; 3627497Sroot 3637497Sroot for (i=0; i<NOFILE; i++) 3647497Sroot if (u.u_ofile[i] == NULL) { 3657497Sroot u.u_r.r_val1 = i; 3667497Sroot u.u_pofile[i] = 0; 3677497Sroot return (i); 3687497Sroot } 3697497Sroot u.u_error = EMFILE; 3707497Sroot return (-1); 3717497Sroot } 3727497Sroot 3737497Sroot struct file *lastf; 3747497Sroot /* 3757497Sroot * Allocate a user file descriptor 3767497Sroot * and a file structure. 3777497Sroot * Initialize the descriptor 3787497Sroot * to point at the file structure. 3797497Sroot */ 3807497Sroot struct file * 3817497Sroot falloc() 3827497Sroot { 3837422Sroot register struct file *fp; 3847497Sroot register i; 3857422Sroot 3867497Sroot i = ufalloc(); 3877497Sroot if (i < 0) 3887497Sroot return (NULL); 3897497Sroot if (lastf == 0) 3907497Sroot lastf = file; 3917497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3927497Sroot if (fp->f_count == 0) 3937497Sroot goto slot; 3947497Sroot for (fp = file; fp < lastf; fp++) 3957497Sroot if (fp->f_count == 0) 3967497Sroot goto slot; 3977497Sroot tablefull("file"); 3987497Sroot u.u_error = ENFILE; 3997497Sroot return (NULL); 4007497Sroot slot: 4017497Sroot u.u_ofile[i] = fp; 4027497Sroot fp->f_count++; 4037497Sroot fp->f_offset = 0; 4047497Sroot fp->f_inode = 0; 4057497Sroot lastf = fp + 1; 4067497Sroot return (fp); 4077497Sroot } 4087497Sroot /* 4097497Sroot * Convert a user supplied file descriptor into a pointer 4107497Sroot * to a file structure. Only task is to check range of the descriptor. 4117497Sroot * Critical paths should use the GETF macro, defined in inline.h. 4127497Sroot */ 4137497Sroot struct file * 4147497Sroot getf(f) 4157497Sroot register int f; 4167497Sroot { 4177497Sroot register struct file *fp; 4187497Sroot 4197497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 4207497Sroot u.u_error = EBADF; 4217497Sroot return (NULL); 4227497Sroot } 4237497Sroot return (fp); 4247497Sroot } 4257497Sroot 4267497Sroot /* 4277497Sroot * Internal form of close. 4287497Sroot * Decrement reference count on 4297497Sroot * file structure. 4307497Sroot * Also make sure the pipe protocol 4317497Sroot * does not constipate. 4327497Sroot * 4337497Sroot * Decrement reference count on the inode following 4347497Sroot * removal to the referencing file structure. 4357497Sroot * Call device handler on last close. 4367497Sroot * Nouser indicates that the user isn't available to present 4377497Sroot * errors to. 4387696Ssam * 4397696Ssam * Handling locking at this level is RIDICULOUS. 4407497Sroot */ 4417696Ssam closef(fp, nouser, flags) 4427497Sroot register struct file *fp; 4437696Ssam int nouser, flags; 4447497Sroot { 4457497Sroot register struct inode *ip; 4467497Sroot register struct mount *mp; 4477497Sroot int flag, mode; 4487497Sroot dev_t dev; 4497497Sroot register int (*cfunc)(); 4507497Sroot 4517422Sroot if (fp == NULL) 4527422Sroot return; 4537497Sroot if (fp->f_count > 1) { 4547497Sroot fp->f_count--; 4557422Sroot return; 4567422Sroot } 4577497Sroot if (fp->f_type == DTYPE_SOCKET) { 4587497Sroot u.u_error = 0; /* XXX */ 4597497Sroot soclose(fp->f_socket, nouser); 4607497Sroot if (nouser == 0 && u.u_error) 4617497Sroot return; 4627497Sroot fp->f_socket = 0; 4637497Sroot fp->f_count = 0; 4647497Sroot return; 4657497Sroot } 4667497Sroot flag = fp->f_flag; 4677497Sroot ip = fp->f_inode; 4687497Sroot dev = (dev_t)ip->i_rdev; 4697497Sroot mode = ip->i_mode & IFMT; 4707696Ssam flags &= RDLOCK|WRLOCK; /* conservative */ 4717696Ssam if (flags) 4727696Ssam funlocki(ip, flags); 4737497Sroot ilock(ip); 4747497Sroot iput(ip); 4757497Sroot fp->f_count = 0; 4767497Sroot 4777497Sroot switch (mode) { 4787497Sroot 4797497Sroot case IFCHR: 4807497Sroot cfunc = cdevsw[major(dev)].d_close; 4817497Sroot break; 4827497Sroot 4837497Sroot case IFBLK: 4847497Sroot /* 4857497Sroot * We don't want to really close the device if it is mounted 4867497Sroot */ 4877497Sroot for (mp = mount; mp < &mount[NMOUNT]; mp++) 4887497Sroot if (mp->m_bufp != NULL && mp->m_dev == dev) 4897497Sroot return; 4907497Sroot cfunc = bdevsw[major(dev)].d_close; 4917497Sroot break; 4927497Sroot 4937497Sroot default: 4947497Sroot return; 4957497Sroot } 4967497Sroot for (fp = file; fp < fileNFILE; fp++) { 4977497Sroot if (fp->f_type == DTYPE_SOCKET) /* XXX */ 4987497Sroot continue; 4997497Sroot if (fp->f_count && (ip = fp->f_inode) && 5007497Sroot ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 5017497Sroot return; 5027497Sroot } 5037497Sroot if (mode == IFBLK) { 5047497Sroot /* 5057497Sroot * On last close of a block device (that isn't mounted) 5067497Sroot * we must invalidate any in core blocks 5077497Sroot */ 5087497Sroot bflush(dev); 5097497Sroot binval(dev); 5107497Sroot } 5117497Sroot (*cfunc)(dev, flag, fp); 5127422Sroot } 513*8119Sroot 514*8119Sroot opause() 515*8119Sroot { 516*8119Sroot 517*8119Sroot for (;;) 518*8119Sroot sleep((caddr_t)&u, PSLEP); 519*8119Sroot } 520