xref: /csrg-svn/sys/kern/kern_descrip.c (revision 8622)
1*8622Sroot /*	kern_descrip.c	5.13	82/10/17	*/
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]) {
1057696Ssam 		closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]);
1067422Sroot 		if (u.u_error)
1077422Sroot 			return;
1087497Sroot 		/* u.u_ofile[uap->j] = 0; */
1097696Ssam 		/* u.u_pofile[uap->j] = 0; */
1107422Sroot 	}
1117696Ssam 	dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK));
1127696Ssam }
1137696Ssam 
1147696Ssam dupit(fd, fp, lockflags)
1157696Ssam 	int fd;
1167696Ssam 	register struct file *fp;
1177696Ssam 	register int lockflags;
1187696Ssam {
1197696Ssam 
1207696Ssam 	u.u_ofile[fd] = fp;
1217696Ssam 	u.u_pofile[fd] = lockflags;
1227497Sroot 	fp->f_count++;
1237696Ssam 	if (lockflags&RDLOCK)
1247696Ssam 		fp->f_inode->i_rdlockc++;
1257696Ssam 	if (lockflags&WRLOCK)
1267696Ssam 		fp->f_inode->i_wrlockc++;
1277422Sroot }
1287422Sroot 
1297497Sroot close()
1307497Sroot {
1317497Sroot 	register struct a {
1327497Sroot 		int	i;
1337497Sroot 	} *uap = (struct a *)u.u_ap;
1347497Sroot 	register struct file *fp;
1357497Sroot 
1367497Sroot 	fp = getf(uap->i);
1377497Sroot 	if (fp == 0)
1387497Sroot 		return;
1397696Ssam 	closef(fp, 0, u.u_pofile[uap->i]);
1407497Sroot 	/* WHAT IF u.u_error ? */
1417696Ssam 	u.u_ofile[uap->i] = NULL;
1427696Ssam 	u.u_pofile[uap->i] = 0;
1437497Sroot }
1447497Sroot 
1458029Sroot wrap()
1467497Sroot {
1477497Sroot 	register struct a {
1487497Sroot 		int	d;
1497497Sroot 		struct	dtype *dtypeb;
1507497Sroot 	} *uap = (struct a *)u.u_ap;
1517497Sroot 	register struct file *fp;
1527497Sroot 	struct dtype adtype;
1537497Sroot 
1547497Sroot 	fp = getf(uap->d);
1557497Sroot 	if (fp == 0)
1567497Sroot 		return;
1577497Sroot 	if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
1587497Sroot 	    sizeof (struct dtype)) < 0) {
1597497Sroot 		u.u_error = EFAULT;
1607497Sroot 		return;
1617497Sroot 	}
1627497Sroot 	/* DO WRAP */
1637497Sroot }
1647497Sroot 
1658115Sroot int	unselect();
1667422Sroot int	nselcoll;
1677422Sroot /*
1687422Sroot  * Select system call.
1697422Sroot  */
1708098Sroot select()
1717422Sroot {
1727422Sroot 	register struct uap  {
1738145Sroot 		int	nd;
1748145Sroot 		long	*in;
1758145Sroot 		long	*ou;
1768145Sroot 		long	*ex;
1778029Sroot 		struct	timeval *tv;
1788029Sroot 	} *uap = (struct uap *)u.u_ap;
1798115Sroot 	int ibits[3], obits[3];
1808115Sroot 	struct timeval atv;
1818586Sroot 	int s, ncoll;
1828115Sroot 	label_t lqsave;
1837422Sroot 
1848145Sroot 	if (uap->nd >= NOFILE) {
1858145Sroot 		u.u_error = EINVAL;
1868145Sroot 		return;
1878145Sroot 	}
1888145Sroot 
1898145Sroot #define	getbits(name, x) \
1908145Sroot 	if (uap->name) { \
1918145Sroot 		if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
1928145Sroot 		    sizeof (ibits[x]))) { \
1938145Sroot 			u.u_error = EFAULT; \
1948145Sroot 			return; \
1958145Sroot 		} \
1968145Sroot 	} else \
1978145Sroot 		ibits[x] = 0;
1988145Sroot 	getbits(in, 0);
1998145Sroot 	getbits(ou, 1);
2008145Sroot 	getbits(ex, 2);
2018145Sroot #undef	getbits
2028145Sroot 
2038029Sroot 	if (uap->tv) {
2048029Sroot 		if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) {
2058029Sroot 			u.u_error = EFAULT;
2068029Sroot 			return;
2078029Sroot 		}
2088115Sroot 		if (itimerfix(&atv)) {
2098115Sroot 			u.u_error = EINVAL;
2108115Sroot 			return;
2118115Sroot 		}
2128115Sroot 		s = spl7(); timevaladd(&atv, &time); splx(s);
2138115Sroot 	}
2147422Sroot retry:
2157422Sroot 	ncoll = nselcoll;
2167422Sroot 	u.u_procp->p_flag |= SSEL;
2178115Sroot 	u.u_r.r_val1 = selscan(ibits, obits);
2187422Sroot 	if (u.u_error)
2198115Sroot 		return;
2208115Sroot 	if (u.u_r.r_val1)
2217422Sroot 		goto done;
2228115Sroot 	s = spl6();
2238145Sroot 	if (uap->tv && timercmp(&time, &atv, >=)) {
2248115Sroot 		splx(s);
2257422Sroot 		goto done;
2268115Sroot 	}
2277422Sroot 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
2287422Sroot 		u.u_procp->p_flag &= ~SSEL;
2297422Sroot 		splx(s);
2307422Sroot 		goto retry;
2317422Sroot 	}
2327422Sroot 	u.u_procp->p_flag &= ~SSEL;
2338115Sroot 	if (uap->tv) {
2348115Sroot 		lqsave = u.u_qsave;
2358115Sroot 		if (setjmp(&u.u_qsave)) {
236*8622Sroot 			untimeout(unselect, (caddr_t)u.u_procp);
2378115Sroot 			u.u_error = EINTR;
2388115Sroot 			splx(s);
2398115Sroot 			return;
2408115Sroot 		}
241*8622Sroot 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
2428115Sroot 	}
2438115Sroot 	sleep((caddr_t)&selwait, PZERO+1);
2448115Sroot 	if (uap->tv) {
2458115Sroot 		u.u_qsave = lqsave;
246*8622Sroot 		untimeout(unselect, (caddr_t)u.u_procp);
2478115Sroot 	}
2487422Sroot 	splx(s);
2498115Sroot 	goto retry;
2508115Sroot done:
2518145Sroot #define	putbits(name, x) \
2528145Sroot 	if (uap->name) { \
2538145Sroot 		if (copyout((caddr_t)obits[x], (caddr_t)uap->name, \
2548145Sroot 		    sizeof (obits[x]))) { \
2558145Sroot 			u.u_error = EFAULT; \
2568145Sroot 			return; \
2578145Sroot 		} \
2588115Sroot 	}
2598145Sroot 	putbits(in, 0);
2608145Sroot 	putbits(ou, 1);
2618145Sroot 	putbits(ex, 2);
2628145Sroot #undef putbits
2638115Sroot }
2647422Sroot 
2658115Sroot unselect(p)
2668115Sroot 	register struct proc *p;
2678115Sroot {
2688115Sroot 	register int s = spl6();
2697422Sroot 
2708115Sroot 	switch (p->p_stat) {
2717422Sroot 
2728115Sroot 	case SSLEEP:
2738115Sroot 		setrun(p);
2747422Sroot 		break;
2758115Sroot 
2768115Sroot 	case SSTOP:
2778115Sroot 		unsleep(p);
2788115Sroot 		break;
2797422Sroot 	}
2808115Sroot 	splx(s);
2817422Sroot }
2827422Sroot 
2838115Sroot selscan(ibits, obits)
2848115Sroot 	int *ibits, *obits;
2857422Sroot {
2868115Sroot 	register int which, bits, i;
2878115Sroot 	int flag;
2887422Sroot 	struct file *fp;
2898115Sroot 	int able;
2907422Sroot 	struct inode *ip;
2918115Sroot 	int n = 0;
2927422Sroot 
2938115Sroot 	for (which = 0; which < 3; which++) {
2948115Sroot 		bits = ibits[which];
2958115Sroot 		obits[which] = 0;
2968115Sroot 		switch (which) {
2977422Sroot 
2988115Sroot 		case 0:
2998115Sroot 			flag = FREAD; break;
3008115Sroot 
3018115Sroot 		case 1:
3028115Sroot 			flag = FWRITE; break;
3038115Sroot 
3048115Sroot 		case 2:
3058115Sroot 			flag = 0; break;
3068115Sroot 		}
3078115Sroot 		while (i = ffs(bits)) {
3088115Sroot 			bits &= ~(1<<(i-1));
3098115Sroot 			fp = u.u_ofile[i-1];
3108115Sroot 			if (fp == NULL) {
3118115Sroot 				u.u_error = EBADF;
3127422Sroot 				break;
3137422Sroot 			}
3148115Sroot 			if (fp->f_type == DTYPE_SOCKET)
3158115Sroot 				able = soselect(fp->f_socket, flag);
3168115Sroot 			else {
3178115Sroot 				ip = fp->f_inode;
3188115Sroot 				switch (ip->i_mode & IFMT) {
3197497Sroot 
3208115Sroot 				case IFCHR:
3218115Sroot 					able =
3228115Sroot 					    (*cdevsw[major(ip->i_rdev)].d_select)
3238115Sroot 						(ip->i_rdev, flag);
3248115Sroot 					break;
3258115Sroot 
3268115Sroot 				case IFBLK:
3278115Sroot 				case IFREG:
3288115Sroot 				case IFDIR:
3298115Sroot 					able = 1;
3308115Sroot 					break;
3318115Sroot 				}
3328115Sroot 
3338115Sroot 			}
3348115Sroot 			if (able) {
3358115Sroot 				obits[which] |= (1<<(i-1));
3368115Sroot 				n++;
3378115Sroot 			}
3387422Sroot 		}
3397422Sroot 	}
3408115Sroot 	return (n);
3417422Sroot }
3427422Sroot 
3437422Sroot /*ARGSUSED*/
3447422Sroot seltrue(dev, flag)
3457422Sroot 	dev_t dev;
3467422Sroot 	int flag;
3477422Sroot {
3487422Sroot 
3497422Sroot 	return (1);
3507422Sroot }
3517422Sroot 
3527422Sroot selwakeup(p, coll)
3537422Sroot 	register struct proc *p;
3547422Sroot 	int coll;
3557422Sroot {
3567422Sroot 	int s;
3577422Sroot 
3587422Sroot 	if (coll) {
3597422Sroot 		nselcoll++;
3607422Sroot 		wakeup((caddr_t)&selwait);
3617422Sroot 	}
3627422Sroot 	if (p) {
3637422Sroot 		if (p->p_wchan == (caddr_t)&selwait)
3647422Sroot 			setrun(p);
3657422Sroot 		else {
3667422Sroot 			s = spl6();
3677422Sroot 			if (p->p_flag & SSEL)
3687422Sroot 				p->p_flag &= ~SSEL;
3697422Sroot 			splx(s);
3707422Sroot 		}
3717422Sroot 	}
3727422Sroot }
3737422Sroot 
3748029Sroot revoke()
3758029Sroot {
3768029Sroot 
3778029Sroot 	/* XXX */
3788029Sroot }
3798029Sroot 
3807422Sroot /*
3817497Sroot  * Allocate a user file descriptor.
3827422Sroot  */
3837497Sroot ufalloc()
3847422Sroot {
3857497Sroot 	register i;
3867497Sroot 
3877497Sroot 	for (i=0; i<NOFILE; i++)
3887497Sroot 		if (u.u_ofile[i] == NULL) {
3897497Sroot 			u.u_r.r_val1 = i;
3907497Sroot 			u.u_pofile[i] = 0;
3917497Sroot 			return (i);
3927497Sroot 		}
3937497Sroot 	u.u_error = EMFILE;
3947497Sroot 	return (-1);
3957497Sroot }
3967497Sroot 
3977497Sroot struct	file *lastf;
3987497Sroot /*
3997497Sroot  * Allocate a user file descriptor
4007497Sroot  * and a file structure.
4017497Sroot  * Initialize the descriptor
4027497Sroot  * to point at the file structure.
4037497Sroot  */
4047497Sroot struct file *
4057497Sroot falloc()
4067497Sroot {
4077422Sroot 	register struct file *fp;
4087497Sroot 	register i;
4097422Sroot 
4107497Sroot 	i = ufalloc();
4117497Sroot 	if (i < 0)
4127497Sroot 		return (NULL);
4137497Sroot 	if (lastf == 0)
4147497Sroot 		lastf = file;
4157497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
4167497Sroot 		if (fp->f_count == 0)
4177497Sroot 			goto slot;
4187497Sroot 	for (fp = file; fp < lastf; fp++)
4197497Sroot 		if (fp->f_count == 0)
4207497Sroot 			goto slot;
4217497Sroot 	tablefull("file");
4227497Sroot 	u.u_error = ENFILE;
4237497Sroot 	return (NULL);
4247497Sroot slot:
4257497Sroot 	u.u_ofile[i] = fp;
4267497Sroot 	fp->f_count++;
4277497Sroot 	fp->f_offset = 0;
4287497Sroot 	fp->f_inode = 0;
4297497Sroot 	lastf = fp + 1;
4307497Sroot 	return (fp);
4317497Sroot }
4327497Sroot /*
4337497Sroot  * Convert a user supplied file descriptor into a pointer
4347497Sroot  * to a file structure.  Only task is to check range of the descriptor.
4357497Sroot  * Critical paths should use the GETF macro, defined in inline.h.
4367497Sroot  */
4377497Sroot struct file *
4387497Sroot getf(f)
4397497Sroot 	register int f;
4407497Sroot {
4417497Sroot 	register struct file *fp;
4427497Sroot 
4437497Sroot 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
4447497Sroot 		u.u_error = EBADF;
4457497Sroot 		return (NULL);
4467497Sroot 	}
4477497Sroot 	return (fp);
4487497Sroot }
4497497Sroot 
4507497Sroot /*
4517497Sroot  * Internal form of close.
4527497Sroot  * Decrement reference count on
4537497Sroot  * file structure.
4547497Sroot  * Also make sure the pipe protocol
4557497Sroot  * does not constipate.
4567497Sroot  *
4577497Sroot  * Decrement reference count on the inode following
4587497Sroot  * removal to the referencing file structure.
4597497Sroot  * Call device handler on last close.
4607497Sroot  * Nouser indicates that the user isn't available to present
4617497Sroot  * errors to.
4627696Ssam  *
4637696Ssam  * Handling locking at this level is RIDICULOUS.
4647497Sroot  */
4657696Ssam closef(fp, nouser, flags)
4667497Sroot 	register struct file *fp;
4677696Ssam 	int nouser, flags;
4687497Sroot {
4697497Sroot 	register struct inode *ip;
4707497Sroot 	register struct mount *mp;
4717497Sroot 	int flag, mode;
4727497Sroot 	dev_t dev;
4737497Sroot 	register int (*cfunc)();
4747497Sroot 
4757422Sroot 	if (fp == NULL)
4767422Sroot 		return;
4777497Sroot 	if (fp->f_count > 1) {
4787497Sroot 		fp->f_count--;
4797422Sroot 		return;
4807422Sroot 	}
4817497Sroot 	if (fp->f_type == DTYPE_SOCKET) {
4827497Sroot 		u.u_error = 0;			/* XXX */
4837497Sroot 		soclose(fp->f_socket, nouser);
4847497Sroot 		if (nouser == 0 && u.u_error)
4857497Sroot 			return;
4867497Sroot 		fp->f_socket = 0;
4877497Sroot 		fp->f_count = 0;
4887497Sroot 		return;
4897497Sroot 	}
4907497Sroot 	flag = fp->f_flag;
4917497Sroot 	ip = fp->f_inode;
4927497Sroot 	dev = (dev_t)ip->i_rdev;
4937497Sroot 	mode = ip->i_mode & IFMT;
4947696Ssam 	flags &= RDLOCK|WRLOCK;			/* conservative */
4957696Ssam 	if (flags)
4967696Ssam 		funlocki(ip, flags);
4977497Sroot 	ilock(ip);
4987497Sroot 	iput(ip);
4997497Sroot 	fp->f_count = 0;
5007497Sroot 
5017497Sroot 	switch (mode) {
5027497Sroot 
5037497Sroot 	case IFCHR:
5047497Sroot 		cfunc = cdevsw[major(dev)].d_close;
5057497Sroot 		break;
5067497Sroot 
5077497Sroot 	case IFBLK:
5087497Sroot 		/*
5097497Sroot 		 * We don't want to really close the device if it is mounted
5107497Sroot 		 */
5117497Sroot 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
5127497Sroot 			if (mp->m_bufp != NULL && mp->m_dev == dev)
5137497Sroot 				return;
5147497Sroot 		cfunc = bdevsw[major(dev)].d_close;
5157497Sroot 		break;
5167497Sroot 
5177497Sroot 	default:
5187497Sroot 		return;
5197497Sroot 	}
5207497Sroot 	for (fp = file; fp < fileNFILE; fp++) {
5217497Sroot 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
5227497Sroot 			continue;
5237497Sroot 		if (fp->f_count && (ip = fp->f_inode) &&
5247497Sroot 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
5257497Sroot 			return;
5267497Sroot 	}
5277497Sroot 	if (mode == IFBLK) {
5287497Sroot 		/*
5297497Sroot 		 * On last close of a block device (that isn't mounted)
5307497Sroot 		 * we must invalidate any in core blocks
5317497Sroot 		 */
5327497Sroot 		bflush(dev);
5337497Sroot 		binval(dev);
5347497Sroot 	}
5357497Sroot 	(*cfunc)(dev, flag, fp);
5367422Sroot }
5378119Sroot 
5388119Sroot opause()
5398119Sroot {
5408119Sroot 
5418119Sroot 	for (;;)
5428119Sroot 		sleep((caddr_t)&u, PSLEP);
5438119Sroot }
544