xref: /csrg-svn/sys/kern/kern_descrip.c (revision 8145)
1*8145Sroot /*	kern_descrip.c	5.10	82/09/11	*/
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  {
174*8145Sroot 		int	nd;
175*8145Sroot 		long	*in;
176*8145Sroot 		long	*ou;
177*8145Sroot 		long	*ex;
1788029Sroot 		struct	timeval *tv;
1798029Sroot 	} *uap = (struct uap *)u.u_ap;
1808115Sroot 	int ibits[3], obits[3];
1818115Sroot 	struct timeval atv;
1827422Sroot 	int s, tsel, ncoll, rem;
1838115Sroot 	label_t lqsave;
1847422Sroot 
185*8145Sroot 	if (uap->nd >= NOFILE) {
186*8145Sroot 		u.u_error = EINVAL;
187*8145Sroot 		return;
188*8145Sroot 	}
189*8145Sroot 
190*8145Sroot #define	getbits(name, x) \
191*8145Sroot 	if (uap->name) { \
192*8145Sroot 		if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
193*8145Sroot 		    sizeof (ibits[x]))) { \
194*8145Sroot 			u.u_error = EFAULT; \
195*8145Sroot 			return; \
196*8145Sroot 		} \
197*8145Sroot 	} else \
198*8145Sroot 		ibits[x] = 0;
199*8145Sroot 	getbits(in, 0);
200*8145Sroot 	getbits(ou, 1);
201*8145Sroot 	getbits(ex, 2);
202*8145Sroot #undef	getbits
203*8145Sroot 
2048029Sroot 	if (uap->tv) {
2058029Sroot 		if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) {
2068029Sroot 			u.u_error = EFAULT;
2078029Sroot 			return;
2088029Sroot 		}
2098115Sroot 		if (itimerfix(&atv)) {
2108115Sroot 			u.u_error = EINVAL;
2118115Sroot 			return;
2128115Sroot 		}
2138115Sroot 		s = spl7(); timevaladd(&atv, &time); splx(s);
2148115Sroot 	}
2157422Sroot retry:
2167422Sroot 	ncoll = nselcoll;
2177422Sroot 	u.u_procp->p_flag |= SSEL;
2188115Sroot 	u.u_r.r_val1 = selscan(ibits, obits);
2197422Sroot 	if (u.u_error)
2208115Sroot 		return;
2218115Sroot 	if (u.u_r.r_val1)
2227422Sroot 		goto done;
2238115Sroot 	s = spl6();
224*8145Sroot 	if (uap->tv && timercmp(&time, &atv, >=)) {
2258115Sroot 		splx(s);
2267422Sroot 		goto done;
2278115Sroot 	}
2287422Sroot 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
2297422Sroot 		u.u_procp->p_flag &= ~SSEL;
2307422Sroot 		splx(s);
2317422Sroot 		goto retry;
2327422Sroot 	}
2337422Sroot 	u.u_procp->p_flag &= ~SSEL;
2348115Sroot 	if (uap->tv) {
2358115Sroot 		lqsave = u.u_qsave;
2368115Sroot 		if (setjmp(&u.u_qsave)) {
2378115Sroot 			untimeout(unselect, u.u_procp);
2388115Sroot 			u.u_error = EINTR;
2398115Sroot 			splx(s);
2408115Sroot 			return;
2418115Sroot 		}
2428115Sroot 		timeout(unselect, u.u_procp, hzto(&atv));
2438115Sroot 	}
2448115Sroot 	sleep((caddr_t)&selwait, PZERO+1);
2458115Sroot 	if (uap->tv) {
2468115Sroot 		u.u_qsave = lqsave;
2478115Sroot 		untimeout(unselect, u.u_procp);
2488115Sroot 	}
2497422Sroot 	splx(s);
2508115Sroot 	goto retry;
2518115Sroot done:
252*8145Sroot #define	putbits(name, x) \
253*8145Sroot 	if (uap->name) { \
254*8145Sroot 		if (copyout((caddr_t)obits[x], (caddr_t)uap->name, \
255*8145Sroot 		    sizeof (obits[x]))) { \
256*8145Sroot 			u.u_error = EFAULT; \
257*8145Sroot 			return; \
258*8145Sroot 		} \
2598115Sroot 	}
260*8145Sroot 	putbits(in, 0);
261*8145Sroot 	putbits(ou, 1);
262*8145Sroot 	putbits(ex, 2);
263*8145Sroot #undef putbits
2648115Sroot }
2657422Sroot 
2668115Sroot unselect(p)
2678115Sroot 	register struct proc *p;
2688115Sroot {
2698115Sroot 	register int s = spl6();
2707422Sroot 
2718115Sroot 	switch (p->p_stat) {
2727422Sroot 
2738115Sroot 	case SSLEEP:
2748115Sroot 		setrun(p);
2757422Sroot 		break;
2768115Sroot 
2778115Sroot 	case SSTOP:
2788115Sroot 		unsleep(p);
2798115Sroot 		break;
2807422Sroot 	}
2818115Sroot 	splx(s);
2827422Sroot }
2837422Sroot 
2848115Sroot selscan(ibits, obits)
2858115Sroot 	int *ibits, *obits;
2867422Sroot {
2878115Sroot 	register int which, bits, i;
2888115Sroot 	int flag;
2897422Sroot 	struct file *fp;
2908115Sroot 	int able;
2917422Sroot 	struct inode *ip;
2928115Sroot 	int n = 0;
2937422Sroot 
2948115Sroot 	for (which = 0; which < 3; which++) {
2958115Sroot 		bits = ibits[which];
2968115Sroot 		obits[which] = 0;
2978115Sroot 		switch (which) {
2987422Sroot 
2998115Sroot 		case 0:
3008115Sroot 			flag = FREAD; break;
3018115Sroot 
3028115Sroot 		case 1:
3038115Sroot 			flag = FWRITE; break;
3048115Sroot 
3058115Sroot 		case 2:
3068115Sroot 			flag = 0; break;
3078115Sroot 		}
3088115Sroot 		while (i = ffs(bits)) {
3098115Sroot 			bits &= ~(1<<(i-1));
3108115Sroot 			fp = u.u_ofile[i-1];
3118115Sroot 			if (fp == NULL) {
3128115Sroot 				u.u_error = EBADF;
3137422Sroot 				break;
3147422Sroot 			}
3158115Sroot 			if (fp->f_type == DTYPE_SOCKET)
3168115Sroot 				able = soselect(fp->f_socket, flag);
3178115Sroot 			else {
3188115Sroot 				ip = fp->f_inode;
3198115Sroot 				switch (ip->i_mode & IFMT) {
3207497Sroot 
3218115Sroot 				case IFCHR:
3228115Sroot 					able =
3238115Sroot 					    (*cdevsw[major(ip->i_rdev)].d_select)
3248115Sroot 						(ip->i_rdev, flag);
3258115Sroot 					break;
3268115Sroot 
3278115Sroot 				case IFBLK:
3288115Sroot 				case IFREG:
3298115Sroot 				case IFDIR:
3308115Sroot 					able = 1;
3318115Sroot 					break;
3328115Sroot 				}
3338115Sroot 
3348115Sroot 			}
3358115Sroot 			if (able) {
3368115Sroot 				obits[which] |= (1<<(i-1));
3378115Sroot 				n++;
3388115Sroot 			}
3397422Sroot 		}
3407422Sroot 	}
3418115Sroot 	return (n);
3427422Sroot }
3437422Sroot 
3447422Sroot /*ARGSUSED*/
3457422Sroot seltrue(dev, flag)
3467422Sroot 	dev_t dev;
3477422Sroot 	int flag;
3487422Sroot {
3497422Sroot 
3507422Sroot 	return (1);
3517422Sroot }
3527422Sroot 
3537422Sroot selwakeup(p, coll)
3547422Sroot 	register struct proc *p;
3557422Sroot 	int coll;
3567422Sroot {
3577422Sroot 	int s;
3587422Sroot 
3597422Sroot 	if (coll) {
3607422Sroot 		nselcoll++;
3617422Sroot 		wakeup((caddr_t)&selwait);
3627422Sroot 	}
3637422Sroot 	if (p) {
3647422Sroot 		if (p->p_wchan == (caddr_t)&selwait)
3657422Sroot 			setrun(p);
3667422Sroot 		else {
3677422Sroot 			s = spl6();
3687422Sroot 			if (p->p_flag & SSEL)
3697422Sroot 				p->p_flag &= ~SSEL;
3707422Sroot 			splx(s);
3717422Sroot 		}
3727422Sroot 	}
3737422Sroot }
3747422Sroot 
3758029Sroot revoke()
3768029Sroot {
3778029Sroot 
3788029Sroot 	/* XXX */
3798029Sroot }
3808029Sroot 
3817422Sroot /*
3827497Sroot  * Allocate a user file descriptor.
3837422Sroot  */
3847497Sroot ufalloc()
3857422Sroot {
3867497Sroot 	register i;
3877497Sroot 
3887497Sroot 	for (i=0; i<NOFILE; i++)
3897497Sroot 		if (u.u_ofile[i] == NULL) {
3907497Sroot 			u.u_r.r_val1 = i;
3917497Sroot 			u.u_pofile[i] = 0;
3927497Sroot 			return (i);
3937497Sroot 		}
3947497Sroot 	u.u_error = EMFILE;
3957497Sroot 	return (-1);
3967497Sroot }
3977497Sroot 
3987497Sroot struct	file *lastf;
3997497Sroot /*
4007497Sroot  * Allocate a user file descriptor
4017497Sroot  * and a file structure.
4027497Sroot  * Initialize the descriptor
4037497Sroot  * to point at the file structure.
4047497Sroot  */
4057497Sroot struct file *
4067497Sroot falloc()
4077497Sroot {
4087422Sroot 	register struct file *fp;
4097497Sroot 	register i;
4107422Sroot 
4117497Sroot 	i = ufalloc();
4127497Sroot 	if (i < 0)
4137497Sroot 		return (NULL);
4147497Sroot 	if (lastf == 0)
4157497Sroot 		lastf = file;
4167497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
4177497Sroot 		if (fp->f_count == 0)
4187497Sroot 			goto slot;
4197497Sroot 	for (fp = file; fp < lastf; fp++)
4207497Sroot 		if (fp->f_count == 0)
4217497Sroot 			goto slot;
4227497Sroot 	tablefull("file");
4237497Sroot 	u.u_error = ENFILE;
4247497Sroot 	return (NULL);
4257497Sroot slot:
4267497Sroot 	u.u_ofile[i] = fp;
4277497Sroot 	fp->f_count++;
4287497Sroot 	fp->f_offset = 0;
4297497Sroot 	fp->f_inode = 0;
4307497Sroot 	lastf = fp + 1;
4317497Sroot 	return (fp);
4327497Sroot }
4337497Sroot /*
4347497Sroot  * Convert a user supplied file descriptor into a pointer
4357497Sroot  * to a file structure.  Only task is to check range of the descriptor.
4367497Sroot  * Critical paths should use the GETF macro, defined in inline.h.
4377497Sroot  */
4387497Sroot struct file *
4397497Sroot getf(f)
4407497Sroot 	register int f;
4417497Sroot {
4427497Sroot 	register struct file *fp;
4437497Sroot 
4447497Sroot 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
4457497Sroot 		u.u_error = EBADF;
4467497Sroot 		return (NULL);
4477497Sroot 	}
4487497Sroot 	return (fp);
4497497Sroot }
4507497Sroot 
4517497Sroot /*
4527497Sroot  * Internal form of close.
4537497Sroot  * Decrement reference count on
4547497Sroot  * file structure.
4557497Sroot  * Also make sure the pipe protocol
4567497Sroot  * does not constipate.
4577497Sroot  *
4587497Sroot  * Decrement reference count on the inode following
4597497Sroot  * removal to the referencing file structure.
4607497Sroot  * Call device handler on last close.
4617497Sroot  * Nouser indicates that the user isn't available to present
4627497Sroot  * errors to.
4637696Ssam  *
4647696Ssam  * Handling locking at this level is RIDICULOUS.
4657497Sroot  */
4667696Ssam closef(fp, nouser, flags)
4677497Sroot 	register struct file *fp;
4687696Ssam 	int nouser, flags;
4697497Sroot {
4707497Sroot 	register struct inode *ip;
4717497Sroot 	register struct mount *mp;
4727497Sroot 	int flag, mode;
4737497Sroot 	dev_t dev;
4747497Sroot 	register int (*cfunc)();
4757497Sroot 
4767422Sroot 	if (fp == NULL)
4777422Sroot 		return;
4787497Sroot 	if (fp->f_count > 1) {
4797497Sroot 		fp->f_count--;
4807422Sroot 		return;
4817422Sroot 	}
4827497Sroot 	if (fp->f_type == DTYPE_SOCKET) {
4837497Sroot 		u.u_error = 0;			/* XXX */
4847497Sroot 		soclose(fp->f_socket, nouser);
4857497Sroot 		if (nouser == 0 && u.u_error)
4867497Sroot 			return;
4877497Sroot 		fp->f_socket = 0;
4887497Sroot 		fp->f_count = 0;
4897497Sroot 		return;
4907497Sroot 	}
4917497Sroot 	flag = fp->f_flag;
4927497Sroot 	ip = fp->f_inode;
4937497Sroot 	dev = (dev_t)ip->i_rdev;
4947497Sroot 	mode = ip->i_mode & IFMT;
4957696Ssam 	flags &= RDLOCK|WRLOCK;			/* conservative */
4967696Ssam 	if (flags)
4977696Ssam 		funlocki(ip, flags);
4987497Sroot 	ilock(ip);
4997497Sroot 	iput(ip);
5007497Sroot 	fp->f_count = 0;
5017497Sroot 
5027497Sroot 	switch (mode) {
5037497Sroot 
5047497Sroot 	case IFCHR:
5057497Sroot 		cfunc = cdevsw[major(dev)].d_close;
5067497Sroot 		break;
5077497Sroot 
5087497Sroot 	case IFBLK:
5097497Sroot 		/*
5107497Sroot 		 * We don't want to really close the device if it is mounted
5117497Sroot 		 */
5127497Sroot 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
5137497Sroot 			if (mp->m_bufp != NULL && mp->m_dev == dev)
5147497Sroot 				return;
5157497Sroot 		cfunc = bdevsw[major(dev)].d_close;
5167497Sroot 		break;
5177497Sroot 
5187497Sroot 	default:
5197497Sroot 		return;
5207497Sroot 	}
5217497Sroot 	for (fp = file; fp < fileNFILE; fp++) {
5227497Sroot 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
5237497Sroot 			continue;
5247497Sroot 		if (fp->f_count && (ip = fp->f_inode) &&
5257497Sroot 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
5267497Sroot 			return;
5277497Sroot 	}
5287497Sroot 	if (mode == IFBLK) {
5297497Sroot 		/*
5307497Sroot 		 * On last close of a block device (that isn't mounted)
5317497Sroot 		 * we must invalidate any in core blocks
5327497Sroot 		 */
5337497Sroot 		bflush(dev);
5347497Sroot 		binval(dev);
5357497Sroot 	}
5367497Sroot 	(*cfunc)(dev, flag, fp);
5377422Sroot }
5388119Sroot 
5398119Sroot opause()
5408119Sroot {
5418119Sroot 
5428119Sroot 	for (;;)
5438119Sroot 		sleep((caddr_t)&u, PSLEP);
5448119Sroot }
545