xref: /csrg-svn/sys/kern/kern_descrip.c (revision 8945)
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