1*8945Sroot /* kern_descrip.c 5.17 82/10/30 */ 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/socket.h" 137422Sroot #include "../h/socketvar.h" 147497Sroot #include "../h/mount.h" 157422Sroot 167497Sroot #include "../h/descrip.h" 177497Sroot 187422Sroot /* 197497Sroot * Descriptor management. 207422Sroot */ 217497Sroot 227497Sroot /* 237497Sroot * TODO: 247497Sroot * getf should be renamed 257497Sroot * ufalloc side effects are gross 267497Sroot */ 277497Sroot 287497Sroot /* 297497Sroot * System calls on descriptors. 307497Sroot */ 318029Sroot getdtablesize() 327497Sroot { 337497Sroot 347497Sroot u.u_r.r_val1 = NOFILE; 357497Sroot } 367497Sroot 378098Sroot getdprop() 388098Sroot { 398098Sroot register struct a { 408098Sroot int d; 418098Sroot struct dtype *dtypeb; 428098Sroot } *uap = (struct a *)u.u_ap; 438098Sroot register struct file *fp; 448098Sroot struct dtype adtype; 458098Sroot 468098Sroot fp = getf(uap->d); 478098Sroot if (fp == 0) 488098Sroot return; 498098Sroot adtype.dt_type = 0; /* XXX */ 508098Sroot adtype.dt_protocol = 0; /* XXX */ 518098Sroot if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 528098Sroot sizeof (struct dtype)) < 0) { 538098Sroot u.u_error = EFAULT; 548098Sroot return; 558098Sroot } 568098Sroot } 578098Sroot 588098Sroot getdopt() 598098Sroot { 608098Sroot 618098Sroot } 628098Sroot 638098Sroot setdopt() 648098Sroot { 658098Sroot 668098Sroot } 678098Sroot 687422Sroot dup() 697422Sroot { 707497Sroot register struct a { 717497Sroot int i; 727497Sroot } *uap = (struct a *) u.u_ap; 737696Ssam struct file *fp; 747696Ssam int j; 757497Sroot 767497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 777497Sroot 787497Sroot fp = getf(uap->i); 797497Sroot if (fp == 0) 807497Sroot return; 817497Sroot j = ufalloc(); 827497Sroot if (j < 0) 837497Sroot return; 847696Ssam dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 857497Sroot } 867497Sroot 877497Sroot dup2() 887497Sroot { 897422Sroot register struct a { 907497Sroot int i, j; 917497Sroot } *uap = (struct a *) u.u_ap; 927497Sroot register struct file *fp; 937422Sroot 947497Sroot fp = getf(uap->i); 957497Sroot if (fp == 0) 967422Sroot return; 977497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 987497Sroot u.u_error = EBADF; 997497Sroot return; 1007422Sroot } 1017497Sroot u.u_r.r_val1 = uap->j; 1027497Sroot if (uap->i == uap->j) 1037497Sroot return; 1047497Sroot if (u.u_ofile[uap->j]) { 105*8945Sroot #ifdef SUNMMAP 106*8945Sroot if (u.u_pofile[uap->j] & UF_MAPPED) 107*8945Sroot munmapfd(uap->j); 108*8945Sroot #endif 1097696Ssam closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); 1107422Sroot if (u.u_error) 1117422Sroot return; 1127497Sroot /* u.u_ofile[uap->j] = 0; */ 1137696Ssam /* u.u_pofile[uap->j] = 0; */ 1147422Sroot } 1157696Ssam dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 1167696Ssam } 1177696Ssam 1187696Ssam dupit(fd, fp, lockflags) 1197696Ssam int fd; 1207696Ssam register struct file *fp; 1217696Ssam register int lockflags; 1227696Ssam { 1237696Ssam 1247696Ssam u.u_ofile[fd] = fp; 1257696Ssam u.u_pofile[fd] = lockflags; 1267497Sroot fp->f_count++; 1277696Ssam if (lockflags&RDLOCK) 1287696Ssam fp->f_inode->i_rdlockc++; 1297696Ssam if (lockflags&WRLOCK) 1307696Ssam fp->f_inode->i_wrlockc++; 1317422Sroot } 1327422Sroot 1337497Sroot close() 1347497Sroot { 1357497Sroot register struct a { 1367497Sroot int i; 1377497Sroot } *uap = (struct a *)u.u_ap; 1387497Sroot register struct file *fp; 1397497Sroot 1407497Sroot fp = getf(uap->i); 1417497Sroot if (fp == 0) 1427497Sroot return; 143*8945Sroot #ifdef SUNMMAP 144*8945Sroot if (u.u_pofile[uap->i] & UF_MAPPED) 145*8945Sroot munmapfd(uap->i); 146*8945Sroot #endif 1477696Ssam closef(fp, 0, u.u_pofile[uap->i]); 1487497Sroot /* WHAT IF u.u_error ? */ 1497696Ssam u.u_ofile[uap->i] = NULL; 1507696Ssam u.u_pofile[uap->i] = 0; 1517497Sroot } 1527497Sroot 1538029Sroot wrap() 1547497Sroot { 1557497Sroot register struct a { 1567497Sroot int d; 1577497Sroot struct dtype *dtypeb; 1587497Sroot } *uap = (struct a *)u.u_ap; 1597497Sroot register struct file *fp; 1607497Sroot struct dtype adtype; 1617497Sroot 1627497Sroot fp = getf(uap->d); 1637497Sroot if (fp == 0) 1647497Sroot return; 1657497Sroot if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 1667497Sroot sizeof (struct dtype)) < 0) { 1677497Sroot u.u_error = EFAULT; 1687497Sroot return; 1697497Sroot } 1707497Sroot /* DO WRAP */ 1717497Sroot } 1727497Sroot 1738115Sroot int unselect(); 1747422Sroot int nselcoll; 1757422Sroot /* 1767422Sroot * Select system call. 1777422Sroot */ 1788098Sroot select() 1797422Sroot { 1807422Sroot register struct uap { 1818145Sroot int nd; 1828145Sroot long *in; 1838145Sroot long *ou; 1848145Sroot long *ex; 1858029Sroot struct timeval *tv; 1868029Sroot } *uap = (struct uap *)u.u_ap; 1878115Sroot int ibits[3], obits[3]; 1888115Sroot struct timeval atv; 1898586Sroot int s, ncoll; 1908115Sroot label_t lqsave; 1917422Sroot 1928809Sroot obits[0] = obits[1] = obits[2] = 0; 1938836Sroot if (uap->nd > NOFILE) 1948836Sroot uap->nd = NOFILE; /* forgiving, if slightly wrong */ 1958145Sroot 1968145Sroot #define getbits(name, x) \ 1978145Sroot if (uap->name) { \ 1988145Sroot if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 1998145Sroot sizeof (ibits[x]))) { \ 2008145Sroot u.u_error = EFAULT; \ 2018809Sroot goto done; \ 2028145Sroot } \ 2038145Sroot } else \ 2048145Sroot ibits[x] = 0; 2058145Sroot getbits(in, 0); 2068145Sroot getbits(ou, 1); 2078145Sroot getbits(ex, 2); 2088145Sroot #undef getbits 2098145Sroot 2108029Sroot if (uap->tv) { 2118029Sroot if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 2128029Sroot u.u_error = EFAULT; 2138809Sroot goto done; 2148029Sroot } 2158115Sroot if (itimerfix(&atv)) { 2168115Sroot u.u_error = EINVAL; 2178809Sroot goto done; 2188115Sroot } 2198115Sroot s = spl7(); timevaladd(&atv, &time); splx(s); 2208115Sroot } 2217422Sroot retry: 2227422Sroot ncoll = nselcoll; 2237422Sroot u.u_procp->p_flag |= SSEL; 2248115Sroot u.u_r.r_val1 = selscan(ibits, obits); 2258809Sroot if (u.u_error || u.u_r.r_val1) 2267422Sroot goto done; 2278115Sroot s = spl6(); 2288145Sroot if (uap->tv && timercmp(&time, &atv, >=)) { 2298115Sroot splx(s); 2307422Sroot goto done; 2318115Sroot } 2327422Sroot if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 2337422Sroot u.u_procp->p_flag &= ~SSEL; 2347422Sroot splx(s); 2357422Sroot goto retry; 2367422Sroot } 2377422Sroot u.u_procp->p_flag &= ~SSEL; 2388115Sroot if (uap->tv) { 2398115Sroot lqsave = u.u_qsave; 2408115Sroot if (setjmp(&u.u_qsave)) { 2418622Sroot untimeout(unselect, (caddr_t)u.u_procp); 2428115Sroot u.u_error = EINTR; 2438115Sroot splx(s); 2448809Sroot goto done; 2458115Sroot } 2468622Sroot timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 2478115Sroot } 2488115Sroot sleep((caddr_t)&selwait, PZERO+1); 2498115Sroot if (uap->tv) { 2508115Sroot u.u_qsave = lqsave; 2518622Sroot untimeout(unselect, (caddr_t)u.u_procp); 2528115Sroot } 2537422Sroot splx(s); 2548115Sroot goto retry; 2558115Sroot done: 2568145Sroot #define putbits(name, x) \ 2578145Sroot if (uap->name) { \ 2588836Sroot if (copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 2598809Sroot sizeof (obits[x]))) \ 2608145Sroot u.u_error = EFAULT; \ 2618115Sroot } 2628145Sroot putbits(in, 0); 2638145Sroot putbits(ou, 1); 2648145Sroot putbits(ex, 2); 2658145Sroot #undef putbits 2668115Sroot } 2677422Sroot 2688115Sroot unselect(p) 2698115Sroot register struct proc *p; 2708115Sroot { 2718115Sroot register int s = spl6(); 2727422Sroot 2738115Sroot switch (p->p_stat) { 2747422Sroot 2758115Sroot case SSLEEP: 2768115Sroot setrun(p); 2777422Sroot break; 2788115Sroot 2798115Sroot case SSTOP: 2808115Sroot unsleep(p); 2818115Sroot break; 2827422Sroot } 2838115Sroot splx(s); 2847422Sroot } 2857422Sroot 2868115Sroot selscan(ibits, obits) 2878115Sroot int *ibits, *obits; 2887422Sroot { 2898115Sroot register int which, bits, i; 2908115Sroot int flag; 2917422Sroot struct file *fp; 2928115Sroot int able; 2937422Sroot struct inode *ip; 2948115Sroot int n = 0; 2957422Sroot 2968115Sroot for (which = 0; which < 3; which++) { 2978115Sroot bits = ibits[which]; 2988115Sroot obits[which] = 0; 2998115Sroot switch (which) { 3007422Sroot 3018115Sroot case 0: 3028115Sroot flag = FREAD; break; 3038115Sroot 3048115Sroot case 1: 3058115Sroot flag = FWRITE; break; 3068115Sroot 3078115Sroot case 2: 3088115Sroot flag = 0; break; 3098115Sroot } 3108115Sroot while (i = ffs(bits)) { 3118115Sroot bits &= ~(1<<(i-1)); 3128115Sroot fp = u.u_ofile[i-1]; 3138115Sroot if (fp == NULL) { 3148115Sroot u.u_error = EBADF; 3157422Sroot break; 3167422Sroot } 3178115Sroot if (fp->f_type == DTYPE_SOCKET) 3188115Sroot able = soselect(fp->f_socket, flag); 3198115Sroot else { 3208115Sroot ip = fp->f_inode; 3218115Sroot switch (ip->i_mode & IFMT) { 3227497Sroot 3238115Sroot case IFCHR: 3248115Sroot able = 3258115Sroot (*cdevsw[major(ip->i_rdev)].d_select) 3268115Sroot (ip->i_rdev, flag); 3278115Sroot break; 3288115Sroot 3298115Sroot case IFBLK: 3308115Sroot case IFREG: 3318115Sroot case IFDIR: 3328115Sroot able = 1; 3338115Sroot break; 3348115Sroot } 3358115Sroot 3368115Sroot } 3378115Sroot if (able) { 3388115Sroot obits[which] |= (1<<(i-1)); 3398115Sroot n++; 3408115Sroot } 3417422Sroot } 3427422Sroot } 3438115Sroot return (n); 3447422Sroot } 3457422Sroot 3467422Sroot /*ARGSUSED*/ 3477422Sroot seltrue(dev, flag) 3487422Sroot dev_t dev; 3497422Sroot int flag; 3507422Sroot { 3517422Sroot 3527422Sroot return (1); 3537422Sroot } 3547422Sroot 3557422Sroot selwakeup(p, coll) 3567422Sroot register struct proc *p; 3577422Sroot int coll; 3587422Sroot { 3597422Sroot int s; 3607422Sroot 3617422Sroot if (coll) { 3627422Sroot nselcoll++; 3637422Sroot wakeup((caddr_t)&selwait); 3647422Sroot } 3657422Sroot if (p) { 3667422Sroot if (p->p_wchan == (caddr_t)&selwait) 3677422Sroot setrun(p); 3687422Sroot else { 3697422Sroot s = spl6(); 3707422Sroot if (p->p_flag & SSEL) 3717422Sroot p->p_flag &= ~SSEL; 3727422Sroot splx(s); 3737422Sroot } 3747422Sroot } 3757422Sroot } 3767422Sroot 3778029Sroot revoke() 3788029Sroot { 3798029Sroot 3808029Sroot /* XXX */ 3818029Sroot } 3828029Sroot 3837422Sroot /* 3847497Sroot * Allocate a user file descriptor. 3857422Sroot */ 3867497Sroot ufalloc() 3877422Sroot { 3887497Sroot register i; 3897497Sroot 3907497Sroot for (i=0; i<NOFILE; i++) 3917497Sroot if (u.u_ofile[i] == NULL) { 3927497Sroot u.u_r.r_val1 = i; 3937497Sroot u.u_pofile[i] = 0; 3947497Sroot return (i); 3957497Sroot } 3967497Sroot u.u_error = EMFILE; 3977497Sroot return (-1); 3987497Sroot } 3997497Sroot 4007497Sroot struct file *lastf; 4017497Sroot /* 4027497Sroot * Allocate a user file descriptor 4037497Sroot * and a file structure. 4047497Sroot * Initialize the descriptor 4057497Sroot * to point at the file structure. 4067497Sroot */ 4077497Sroot struct file * 4087497Sroot falloc() 4097497Sroot { 4107422Sroot register struct file *fp; 4117497Sroot register i; 4127422Sroot 4137497Sroot i = ufalloc(); 4147497Sroot if (i < 0) 4157497Sroot return (NULL); 4167497Sroot if (lastf == 0) 4177497Sroot lastf = file; 4187497Sroot for (fp = lastf; fp < fileNFILE; fp++) 4197497Sroot if (fp->f_count == 0) 4207497Sroot goto slot; 4217497Sroot for (fp = file; fp < lastf; fp++) 4227497Sroot if (fp->f_count == 0) 4237497Sroot goto slot; 4247497Sroot tablefull("file"); 4257497Sroot u.u_error = ENFILE; 4267497Sroot return (NULL); 4277497Sroot slot: 4287497Sroot u.u_ofile[i] = fp; 4297497Sroot fp->f_count++; 4307497Sroot fp->f_offset = 0; 4317497Sroot fp->f_inode = 0; 4327497Sroot lastf = fp + 1; 4337497Sroot return (fp); 4347497Sroot } 4357497Sroot /* 4367497Sroot * Convert a user supplied file descriptor into a pointer 4377497Sroot * to a file structure. Only task is to check range of the descriptor. 4387497Sroot * Critical paths should use the GETF macro, defined in inline.h. 4397497Sroot */ 4407497Sroot struct file * 4417497Sroot getf(f) 4427497Sroot register int f; 4437497Sroot { 4447497Sroot register struct file *fp; 4457497Sroot 4467497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 4477497Sroot u.u_error = EBADF; 4487497Sroot return (NULL); 4497497Sroot } 4507497Sroot return (fp); 4517497Sroot } 4527497Sroot 4537497Sroot /* 4547497Sroot * Internal form of close. 4557497Sroot * Decrement reference count on 4567497Sroot * file structure. 4577497Sroot * Also make sure the pipe protocol 4587497Sroot * does not constipate. 4597497Sroot * 4607497Sroot * Decrement reference count on the inode following 4617497Sroot * removal to the referencing file structure. 4627497Sroot * Call device handler on last close. 4637497Sroot * Nouser indicates that the user isn't available to present 4647497Sroot * errors to. 4657696Ssam * 4667696Ssam * Handling locking at this level is RIDICULOUS. 4677497Sroot */ 4687696Ssam closef(fp, nouser, flags) 4697497Sroot register struct file *fp; 4707696Ssam int nouser, flags; 4717497Sroot { 4727497Sroot register struct inode *ip; 4737497Sroot register struct mount *mp; 4747497Sroot int flag, mode; 4757497Sroot dev_t dev; 4767497Sroot register int (*cfunc)(); 4777497Sroot 4787422Sroot if (fp == NULL) 4797422Sroot return; 4807497Sroot if (fp->f_count > 1) { 4817497Sroot fp->f_count--; 4827422Sroot return; 4837422Sroot } 4847497Sroot if (fp->f_type == DTYPE_SOCKET) { 4858689Sroot u.u_error = soclose(fp->f_socket, nouser); 4867497Sroot if (nouser == 0 && u.u_error) 4877497Sroot return; 4887497Sroot fp->f_socket = 0; 4897497Sroot fp->f_count = 0; 4907497Sroot return; 4917497Sroot } 4927497Sroot flag = fp->f_flag; 4937497Sroot ip = fp->f_inode; 4947497Sroot dev = (dev_t)ip->i_rdev; 4957497Sroot mode = ip->i_mode & IFMT; 4967696Ssam flags &= RDLOCK|WRLOCK; /* conservative */ 4977696Ssam if (flags) 4987696Ssam funlocki(ip, flags); 4997497Sroot ilock(ip); 5007497Sroot iput(ip); 5017497Sroot fp->f_count = 0; 5027497Sroot 5037497Sroot switch (mode) { 5047497Sroot 5057497Sroot case IFCHR: 5067497Sroot cfunc = cdevsw[major(dev)].d_close; 5077497Sroot break; 5087497Sroot 5097497Sroot case IFBLK: 5107497Sroot /* 5117497Sroot * We don't want to really close the device if it is mounted 5127497Sroot */ 5137497Sroot for (mp = mount; mp < &mount[NMOUNT]; mp++) 5147497Sroot if (mp->m_bufp != NULL && mp->m_dev == dev) 5157497Sroot return; 5167497Sroot cfunc = bdevsw[major(dev)].d_close; 5177497Sroot break; 5187497Sroot 5197497Sroot default: 5207497Sroot return; 5217497Sroot } 5227497Sroot for (fp = file; fp < fileNFILE; fp++) { 5237497Sroot if (fp->f_type == DTYPE_SOCKET) /* XXX */ 5247497Sroot continue; 5257497Sroot if (fp->f_count && (ip = fp->f_inode) && 5267497Sroot ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 5277497Sroot return; 5287497Sroot } 5297497Sroot if (mode == IFBLK) { 5307497Sroot /* 5317497Sroot * On last close of a block device (that isn't mounted) 5327497Sroot * we must invalidate any in core blocks 5337497Sroot */ 5347497Sroot bflush(dev); 5357497Sroot binval(dev); 5367497Sroot } 5377497Sroot (*cfunc)(dev, flag, fp); 5387422Sroot } 5398119Sroot 5408119Sroot opause() 5418119Sroot { 5428119Sroot 5438119Sroot for (;;) 5448119Sroot sleep((caddr_t)&u, PSLEP); 5458119Sroot } 546