xref: /csrg-svn/sys/kern/kern_descrip.c (revision 8098)
1*8098Sroot /*	kern_descrip.c	5.7	82/09/06	*/
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 
38*8098Sroot getdprop()
39*8098Sroot {
40*8098Sroot 	register struct a {
41*8098Sroot 		int	d;
42*8098Sroot 		struct	dtype *dtypeb;
43*8098Sroot 	} *uap = (struct a *)u.u_ap;
44*8098Sroot 	register struct file *fp;
45*8098Sroot 	struct dtype adtype;
46*8098Sroot 
47*8098Sroot 	fp = getf(uap->d);
48*8098Sroot 	if (fp == 0)
49*8098Sroot 		return;
50*8098Sroot 	adtype.dt_type = 0;		/* XXX */
51*8098Sroot 	adtype.dt_protocol = 0;		/* XXX */
52*8098Sroot 	if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
53*8098Sroot 	    sizeof (struct dtype)) < 0) {
54*8098Sroot 		u.u_error = EFAULT;
55*8098Sroot 		return;
56*8098Sroot 	}
57*8098Sroot }
58*8098Sroot 
59*8098Sroot getdopt()
60*8098Sroot {
61*8098Sroot 
62*8098Sroot }
63*8098Sroot 
64*8098Sroot setdopt()
65*8098Sroot {
66*8098Sroot 
67*8098Sroot }
68*8098Sroot 
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 
1667422Sroot int	nselcoll;
1677422Sroot /*
1687422Sroot  * Select system call.
1697422Sroot  */
170*8098Sroot select()
1717422Sroot {
1727422Sroot 	register struct uap  {
173*8098Sroot 		fd_set	*rp, *wp, *ep;
1748029Sroot 		struct	timeval *tv;
1758029Sroot 	} *uap = (struct uap *)u.u_ap;
1767422Sroot 	fd_set rd, wr;
1777422Sroot 	int nfds = 0, readable = 0, writeable = 0;
1788029Sroot 	struct timeval atv, origin, now;
1797422Sroot 	int s, tsel, ncoll, rem;
1807422Sroot 
1818029Sroot 	if (uap->tv) {
1828029Sroot 		if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) {
1838029Sroot 			u.u_error = EFAULT;
1848029Sroot 			return;
1858029Sroot 		}
1868029Sroot 	} else
1878029Sroot 		timerclear(&atv);
1888029Sroot 	if (uap->rp && copyin((caddr_t)uap->rp,(caddr_t)&rd,sizeof(fd_set)))
1897422Sroot 		return;
1908029Sroot 	if (uap->wp && copyin((caddr_t)uap->wp,(caddr_t)&wr,sizeof(fd_set)))
1917422Sroot 		return;
1927422Sroot retry:
1938029Sroot 	s = spl7(); now = time; splx(s);
1947422Sroot 	ncoll = nselcoll;
1957422Sroot 	u.u_procp->p_flag |= SSEL;
1968029Sroot 	if (uap->rp)
197*8098Sroot 		readable = selscan(rd, &nfds, FREAD);
1988029Sroot 	if (uap->wp)
199*8098Sroot 		writeable = selscan(wr, &nfds, FWRITE);
2007422Sroot 	if (u.u_error)
2017422Sroot 		goto done;
2027422Sroot 	if (readable || writeable)
2037422Sroot 		goto done;
2048029Sroot 	if (!timerisset(&atv))
2057422Sroot 		goto done;
2067422Sroot 	s = spl6();
2077422Sroot 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
2087422Sroot 		u.u_procp->p_flag &= ~SSEL;
2097422Sroot 		splx(s);
2107422Sroot 		goto retry;
2117422Sroot 	}
2127422Sroot 	u.u_procp->p_flag &= ~SSEL;
2138029Sroot 	tsel = tsleep((caddr_t)&selwait, PZERO+1, &atv);
2147422Sroot 	splx(s);
2157422Sroot 	switch (tsel) {
2167422Sroot 
2177422Sroot 	case TS_OK:
2188029Sroot 		now = time;
2198029Sroot 		timevalsub(&now, &origin);
2208029Sroot 		timevalsub(&atv, now);
2218029Sroot 		if (atv.tv_sec < 0 || atv.tv_usec < 0)
2228029Sroot 			timerclear(&atv);
2237422Sroot 		goto retry;
2247422Sroot 
2257422Sroot 	case TS_SIG:
2267422Sroot 		u.u_error = EINTR;
2277422Sroot 		return;
2287422Sroot 
2297422Sroot 	case TS_TIME:
2307422Sroot 		break;
2317422Sroot 	}
2327422Sroot done:
2337422Sroot 	rd.fds_bits[0] = readable;
2347422Sroot 	wr.fds_bits[0] = writeable;
2357422Sroot 	s = sizeof (fd_set);
2367422Sroot 	u.u_r.r_val1 = nfds;
2378029Sroot 	if (uap->rp)
2388029Sroot 		(void) copyout((caddr_t)&rd, (caddr_t)uap->rp, sizeof(fd_set));
2398029Sroot 	if (uap->wp)
2408029Sroot 		(void) copyout((caddr_t)&wr, (caddr_t)uap->wp, sizeof(fd_set));
2417422Sroot }
2427422Sroot 
243*8098Sroot selscan(fds, nfdp, flag)
2447422Sroot 	fd_set fds;
2457422Sroot 	int *nfdp, flag;
2467422Sroot {
2477422Sroot 	struct file *fp;
2487422Sroot 	struct inode *ip;
2497422Sroot 	register int bits;
2507422Sroot 	int i, able, res = 0;
2517422Sroot 
2527422Sroot 	bits = fds.fds_bits[0];
2537422Sroot 	while (i = ffs(bits)) {
2547422Sroot 		bits &= ~(1<<(i-1));
2557422Sroot 		fp = u.u_ofile[i-1];
2567422Sroot 		if (fp == NULL) {
2577422Sroot 			u.u_error = EBADF;
2587422Sroot 			return (0);
2597422Sroot 		}
2607497Sroot 		if (fp->f_type == DTYPE_SOCKET)
2617422Sroot 			able = soselect(fp->f_socket, flag);
2627422Sroot 		else {
2637422Sroot 			ip = fp->f_inode;
2647422Sroot 			switch (ip->i_mode & IFMT) {
2657422Sroot 
2667422Sroot 			case IFCHR:
2677422Sroot 				able =
2687422Sroot 				    (*cdevsw[major(ip->i_rdev)].d_select)
2697422Sroot 					(ip->i_rdev, flag);
2707422Sroot 				break;
2717422Sroot 
2727422Sroot 			case IFBLK:
2737422Sroot 			case IFREG:
2747422Sroot 			case IFDIR:
2757422Sroot 				able = 1;
2767422Sroot 				break;
2777422Sroot 			}
2787497Sroot 
2797422Sroot 		}
2807422Sroot 		if (able) {
2817422Sroot 			res |= (1<<(i-1));
2827422Sroot 			(*nfdp)++;
2837422Sroot 		}
2847422Sroot 	}
2857422Sroot 	return (res);
2867422Sroot }
2877422Sroot 
2887422Sroot /*ARGSUSED*/
2897422Sroot seltrue(dev, flag)
2907422Sroot 	dev_t dev;
2917422Sroot 	int flag;
2927422Sroot {
2937422Sroot 
2947422Sroot 	return (1);
2957422Sroot }
2967422Sroot 
2977422Sroot selwakeup(p, coll)
2987422Sroot 	register struct proc *p;
2997422Sroot 	int coll;
3007422Sroot {
3017422Sroot 	int s;
3027422Sroot 
3037422Sroot 	if (coll) {
3047422Sroot 		nselcoll++;
3057422Sroot 		wakeup((caddr_t)&selwait);
3067422Sroot 	}
3077422Sroot 	if (p) {
3087422Sroot 		if (p->p_wchan == (caddr_t)&selwait)
3097422Sroot 			setrun(p);
3107422Sroot 		else {
3117422Sroot 			s = spl6();
3127422Sroot 			if (p->p_flag & SSEL)
3137422Sroot 				p->p_flag &= ~SSEL;
3147422Sroot 			splx(s);
3157422Sroot 		}
3167422Sroot 	}
3177422Sroot }
3187422Sroot 
3198029Sroot revoke()
3208029Sroot {
3218029Sroot 
3228029Sroot 	/* XXX */
3238029Sroot }
3248029Sroot 
3257422Sroot /*
3267497Sroot  * Allocate a user file descriptor.
3277422Sroot  */
3287497Sroot ufalloc()
3297422Sroot {
3307497Sroot 	register i;
3317497Sroot 
3327497Sroot 	for (i=0; i<NOFILE; i++)
3337497Sroot 		if (u.u_ofile[i] == NULL) {
3347497Sroot 			u.u_r.r_val1 = i;
3357497Sroot 			u.u_pofile[i] = 0;
3367497Sroot 			return (i);
3377497Sroot 		}
3387497Sroot 	u.u_error = EMFILE;
3397497Sroot 	return (-1);
3407497Sroot }
3417497Sroot 
3427497Sroot struct	file *lastf;
3437497Sroot /*
3447497Sroot  * Allocate a user file descriptor
3457497Sroot  * and a file structure.
3467497Sroot  * Initialize the descriptor
3477497Sroot  * to point at the file structure.
3487497Sroot  */
3497497Sroot struct file *
3507497Sroot falloc()
3517497Sroot {
3527422Sroot 	register struct file *fp;
3537497Sroot 	register i;
3547422Sroot 
3557497Sroot 	i = ufalloc();
3567497Sroot 	if (i < 0)
3577497Sroot 		return (NULL);
3587497Sroot 	if (lastf == 0)
3597497Sroot 		lastf = file;
3607497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
3617497Sroot 		if (fp->f_count == 0)
3627497Sroot 			goto slot;
3637497Sroot 	for (fp = file; fp < lastf; fp++)
3647497Sroot 		if (fp->f_count == 0)
3657497Sroot 			goto slot;
3667497Sroot 	tablefull("file");
3677497Sroot 	u.u_error = ENFILE;
3687497Sroot 	return (NULL);
3697497Sroot slot:
3707497Sroot 	u.u_ofile[i] = fp;
3717497Sroot 	fp->f_count++;
3727497Sroot 	fp->f_offset = 0;
3737497Sroot 	fp->f_inode = 0;
3747497Sroot 	lastf = fp + 1;
3757497Sroot 	return (fp);
3767497Sroot }
3777497Sroot /*
3787497Sroot  * Convert a user supplied file descriptor into a pointer
3797497Sroot  * to a file structure.  Only task is to check range of the descriptor.
3807497Sroot  * Critical paths should use the GETF macro, defined in inline.h.
3817497Sroot  */
3827497Sroot struct file *
3837497Sroot getf(f)
3847497Sroot 	register int f;
3857497Sroot {
3867497Sroot 	register struct file *fp;
3877497Sroot 
3887497Sroot 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
3897497Sroot 		u.u_error = EBADF;
3907497Sroot 		return (NULL);
3917497Sroot 	}
3927497Sroot 	return (fp);
3937497Sroot }
3947497Sroot 
3957497Sroot /*
3967497Sroot  * Internal form of close.
3977497Sroot  * Decrement reference count on
3987497Sroot  * file structure.
3997497Sroot  * Also make sure the pipe protocol
4007497Sroot  * does not constipate.
4017497Sroot  *
4027497Sroot  * Decrement reference count on the inode following
4037497Sroot  * removal to the referencing file structure.
4047497Sroot  * Call device handler on last close.
4057497Sroot  * Nouser indicates that the user isn't available to present
4067497Sroot  * errors to.
4077696Ssam  *
4087696Ssam  * Handling locking at this level is RIDICULOUS.
4097497Sroot  */
4107696Ssam closef(fp, nouser, flags)
4117497Sroot 	register struct file *fp;
4127696Ssam 	int nouser, flags;
4137497Sroot {
4147497Sroot 	register struct inode *ip;
4157497Sroot 	register struct mount *mp;
4167497Sroot 	int flag, mode;
4177497Sroot 	dev_t dev;
4187497Sroot 	register int (*cfunc)();
4197497Sroot 
4207422Sroot 	if (fp == NULL)
4217422Sroot 		return;
4227497Sroot 	if (fp->f_count > 1) {
4237497Sroot 		fp->f_count--;
4247422Sroot 		return;
4257422Sroot 	}
4267497Sroot 	if (fp->f_type == DTYPE_SOCKET) {
4277497Sroot 		u.u_error = 0;			/* XXX */
4287497Sroot 		soclose(fp->f_socket, nouser);
4297497Sroot 		if (nouser == 0 && u.u_error)
4307497Sroot 			return;
4317497Sroot 		fp->f_socket = 0;
4327497Sroot 		fp->f_count = 0;
4337497Sroot 		return;
4347497Sroot 	}
4357497Sroot 	flag = fp->f_flag;
4367497Sroot 	ip = fp->f_inode;
4377497Sroot 	dev = (dev_t)ip->i_rdev;
4387497Sroot 	mode = ip->i_mode & IFMT;
4397696Ssam 	flags &= RDLOCK|WRLOCK;			/* conservative */
4407696Ssam 	if (flags)
4417696Ssam 		funlocki(ip, flags);
4427497Sroot 	ilock(ip);
4437497Sroot 	iput(ip);
4447497Sroot 	fp->f_count = 0;
4457497Sroot 
4467497Sroot 	switch (mode) {
4477497Sroot 
4487497Sroot 	case IFCHR:
4497497Sroot 		cfunc = cdevsw[major(dev)].d_close;
4507497Sroot 		break;
4517497Sroot 
4527497Sroot 	case IFBLK:
4537497Sroot 		/*
4547497Sroot 		 * We don't want to really close the device if it is mounted
4557497Sroot 		 */
4567497Sroot 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
4577497Sroot 			if (mp->m_bufp != NULL && mp->m_dev == dev)
4587497Sroot 				return;
4597497Sroot 		cfunc = bdevsw[major(dev)].d_close;
4607497Sroot 		break;
4617497Sroot 
4627497Sroot 	default:
4637497Sroot 		return;
4647497Sroot 	}
4657497Sroot 	for (fp = file; fp < fileNFILE; fp++) {
4667497Sroot 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
4677497Sroot 			continue;
4687497Sroot 		if (fp->f_count && (ip = fp->f_inode) &&
4697497Sroot 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
4707497Sroot 			return;
4717497Sroot 	}
4727497Sroot 	if (mode == IFBLK) {
4737497Sroot 		/*
4747497Sroot 		 * On last close of a block device (that isn't mounted)
4757497Sroot 		 * we must invalidate any in core blocks
4767497Sroot 		 */
4777497Sroot 		bflush(dev);
4787497Sroot 		binval(dev);
4797497Sroot 	}
4807497Sroot 	(*cfunc)(dev, flag, fp);
4817422Sroot }
482