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