xref: /csrg-svn/sys/kern/kern_descrip.c (revision 21101)
1*21101Skarels /*	kern_descrip.c	6.10	85/05/27	*/
27422Sroot 
317089Sbloom #include "param.h"
417089Sbloom #include "systm.h"
517089Sbloom #include "dir.h"
617089Sbloom #include "user.h"
717089Sbloom #include "kernel.h"
817089Sbloom #include "inode.h"
917089Sbloom #include "proc.h"
1017089Sbloom #include "file.h"
1117089Sbloom #include "socket.h"
1217089Sbloom #include "socketvar.h"
1317089Sbloom #include "mount.h"
1417089Sbloom #include "stat.h"
157422Sroot 
1617089Sbloom #include "ioctl.h"
177497Sroot 
187422Sroot /*
197497Sroot  * Descriptor management.
207422Sroot  */
217497Sroot 
227497Sroot /*
237497Sroot  * TODO:
2412748Ssam  *	eliminate u.u_error side effects
257497Sroot  */
267497Sroot 
277497Sroot /*
287497Sroot  * System calls on descriptors.
297497Sroot  */
308029Sroot getdtablesize()
317497Sroot {
327497Sroot 
337497Sroot 	u.u_r.r_val1 = NOFILE;
347497Sroot }
357497Sroot 
368098Sroot getdopt()
378098Sroot {
388098Sroot 
398098Sroot }
408098Sroot 
418098Sroot setdopt()
428098Sroot {
438098Sroot 
448098Sroot }
458098Sroot 
467422Sroot dup()
477422Sroot {
487497Sroot 	register struct a {
497497Sroot 		int	i;
507497Sroot 	} *uap = (struct a *) u.u_ap;
517696Ssam 	struct file *fp;
527696Ssam 	int j;
537497Sroot 
547497Sroot 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
557497Sroot 
5617003Smckusick 	GETF(fp, uap->i);
5712748Ssam 	j = ufalloc(0);
587497Sroot 	if (j < 0)
597497Sroot 		return;
6017435Skarels 	dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
617497Sroot }
627497Sroot 
637497Sroot dup2()
647497Sroot {
657422Sroot 	register struct a {
667497Sroot 		int	i, j;
677497Sroot 	} *uap = (struct a *) u.u_ap;
687497Sroot 	register struct file *fp;
697422Sroot 
7017003Smckusick 	GETF(fp, uap->i);
717497Sroot 	if (uap->j < 0 || uap->j >= NOFILE) {
727497Sroot 		u.u_error = EBADF;
737497Sroot 		return;
747422Sroot 	}
757497Sroot 	u.u_r.r_val1 = uap->j;
767497Sroot 	if (uap->i == uap->j)
777497Sroot 		return;
787497Sroot 	if (u.u_ofile[uap->j]) {
798945Sroot 		if (u.u_pofile[uap->j] & UF_MAPPED)
808945Sroot 			munmapfd(uap->j);
8113101Ssam 		closef(u.u_ofile[uap->j]);
827422Sroot 		if (u.u_error)
837422Sroot 			return;
847422Sroot 	}
8517435Skarels 	dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
867696Ssam }
877696Ssam 
8813101Ssam dupit(fd, fp, flags)
897696Ssam 	int fd;
907696Ssam 	register struct file *fp;
9113101Ssam 	register int flags;
927696Ssam {
937696Ssam 
947696Ssam 	u.u_ofile[fd] = fp;
9513101Ssam 	u.u_pofile[fd] = flags;
967497Sroot 	fp->f_count++;
97*21101Skarels 	if (fd > u.u_lastfile)
98*21101Skarels 		u.u_lastfile = fd;
997422Sroot }
1007422Sroot 
10112748Ssam /*
10212748Ssam  * The file control system call.
10312748Ssam  */
10412748Ssam fcntl()
1057497Sroot {
1067497Sroot 	register struct file *fp;
1077497Sroot 	register struct a {
10812748Ssam 		int	fdes;
10912748Ssam 		int	cmd;
11012748Ssam 		int	arg;
11112748Ssam 	} *uap;
11212748Ssam 	register i;
11312748Ssam 	register char *pop;
1147497Sroot 
11512748Ssam 	uap = (struct a *)u.u_ap;
11617003Smckusick 	GETF(fp, uap->fdes);
11712748Ssam 	pop = &u.u_pofile[uap->fdes];
11812748Ssam 	switch(uap->cmd) {
11915076Skarels 	case F_DUPFD:
12012748Ssam 		i = uap->arg;
12117434Skarels 		if (i < 0 || i >= NOFILE) {
12212748Ssam 			u.u_error = EINVAL;
12312748Ssam 			return;
12412748Ssam 		}
12512748Ssam 		if ((i = ufalloc(i)) < 0)
12612748Ssam 			return;
12717435Skarels 		dupit(i, fp, *pop &~ UF_EXCLOSE);
12812748Ssam 		break;
1297497Sroot 
13015076Skarels 	case F_GETFD:
13112748Ssam 		u.u_r.r_val1 = *pop & 1;
13212748Ssam 		break;
1337422Sroot 
13415076Skarels 	case F_SETFD:
13512748Ssam 		*pop = (*pop &~ 1) | (uap->arg & 1);
13612748Ssam 		break;
1378145Sroot 
13815076Skarels 	case F_GETFL:
13912748Ssam 		u.u_r.r_val1 = fp->f_flag+FOPEN;
14012748Ssam 		break;
1418145Sroot 
14215076Skarels 	case F_SETFL:
14312748Ssam 		fp->f_flag &= FCNTLCANT;
14412748Ssam 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
14512748Ssam 		u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
1469995Ssam 		if (u.u_error)
14712748Ssam 			break;
14812748Ssam 		u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
14912748Ssam 		if (u.u_error)
15012748Ssam 			(void) fset(fp, FNDELAY, 0);
15112748Ssam 		break;
1527422Sroot 
15315076Skarels 	case F_GETOWN:
15415076Skarels 		u.u_error = fgetown(fp, &u.u_r.r_val1);
15512748Ssam 		break;
1567422Sroot 
15715076Skarels 	case F_SETOWN:
15815076Skarels 		u.u_error = fsetown(fp, uap->arg);
1597422Sroot 		break;
1608115Sroot 
16112748Ssam 	default:
16212748Ssam 		u.u_error = EINVAL;
1637422Sroot 	}
1647422Sroot }
1657422Sroot 
16612748Ssam fset(fp, bit, value)
16712748Ssam 	struct file *fp;
16812748Ssam 	int bit, value;
1697422Sroot {
1707422Sroot 
17112748Ssam 	if (value)
17212748Ssam 		fp->f_flag |= bit;
17312748Ssam 	else
17412748Ssam 		fp->f_flag &= ~bit;
17512748Ssam 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
17612748Ssam 	    (caddr_t)&value));
17712748Ssam }
1787422Sroot 
17912748Ssam fgetown(fp, valuep)
18012748Ssam 	struct file *fp;
18112748Ssam 	int *valuep;
18212748Ssam {
18312748Ssam 	int error;
1848115Sroot 
18512748Ssam 	switch (fp->f_type) {
1868115Sroot 
18712748Ssam 	case DTYPE_SOCKET:
18812748Ssam 		*valuep = ((struct socket *)fp->f_data)->so_pgrp;
18912748Ssam 		return (0);
1907497Sroot 
19112748Ssam 	default:
19212748Ssam 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
19312748Ssam 		*valuep = -*valuep;
19412748Ssam 		return (error);
1957422Sroot 	}
1967422Sroot }
1977422Sroot 
19812748Ssam fsetown(fp, value)
19912748Ssam 	struct file *fp;
20012748Ssam 	int value;
2017422Sroot {
2027422Sroot 
20312748Ssam 	if (fp->f_type == DTYPE_SOCKET) {
20412748Ssam 		((struct socket *)fp->f_data)->so_pgrp = value;
20512748Ssam 		return (0);
20612748Ssam 	}
20712748Ssam 	if (value > 0) {
20812748Ssam 		struct proc *p = pfind(value);
20912748Ssam 		if (p == 0)
21012748Ssam 			return (EINVAL);
21112748Ssam 		value = p->p_pgrp;
21212748Ssam 	} else
21312748Ssam 		value = -value;
21412748Ssam 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
2157422Sroot }
2167422Sroot 
21712748Ssam fioctl(fp, cmd, value)
21812748Ssam 	struct file *fp;
21912748Ssam 	int cmd;
22012748Ssam 	caddr_t value;
2217422Sroot {
2227422Sroot 
22312748Ssam 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
2247422Sroot }
2257422Sroot 
22612748Ssam close()
2278029Sroot {
228*21101Skarels 	struct a {
22912748Ssam 		int	i;
23012748Ssam 	} *uap = (struct a *)u.u_ap;
231*21101Skarels 	register int i = uap->i;
23212748Ssam 	register struct file *fp;
23313044Ssam 	register u_char *pf;
2348029Sroot 
235*21101Skarels 	GETF(fp, i);
236*21101Skarels 	pf = (u_char *)&u.u_pofile[i];
23713044Ssam 	if (*pf & UF_MAPPED)
238*21101Skarels 		munmapfd(i);
239*21101Skarels 	u.u_ofile[i] = NULL;
240*21101Skarels 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
241*21101Skarels 		u.u_lastfile--;
24215550Skarels 	*pf = 0;
24313044Ssam 	closef(fp);
24412748Ssam 	/* WHAT IF u.u_error ? */
2458029Sroot }
2468029Sroot 
24713044Ssam fstat()
24813044Ssam {
24913044Ssam 	register struct file *fp;
25013044Ssam 	register struct a {
25113044Ssam 		int	fdes;
25213044Ssam 		struct	stat *sb;
25313044Ssam 	} *uap;
25413044Ssam 	struct stat ub;
25513044Ssam 
25613044Ssam 	uap = (struct a *)u.u_ap;
25717003Smckusick 	GETF(fp, uap->fdes);
25813044Ssam 	switch (fp->f_type) {
25913044Ssam 
26013044Ssam 	case DTYPE_INODE:
26113044Ssam 		u.u_error = ino_stat((struct inode *)fp->f_data, &ub);
26213044Ssam 		break;
26313044Ssam 
26413044Ssam 	case DTYPE_SOCKET:
26513044Ssam 		u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
26613044Ssam 		break;
26713044Ssam 
26813044Ssam 	default:
26913044Ssam 		panic("fstat");
27013044Ssam 		/*NOTREACHED*/
27113044Ssam 	}
27213044Ssam 	if (u.u_error == 0)
27313101Ssam 		u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
27413101Ssam 		    sizeof (ub));
27513044Ssam }
27613044Ssam 
2777422Sroot /*
2787497Sroot  * Allocate a user file descriptor.
2797422Sroot  */
28012748Ssam ufalloc(i)
28112748Ssam 	register int i;
2827422Sroot {
2837497Sroot 
28412748Ssam 	for (; i < NOFILE; i++)
2857497Sroot 		if (u.u_ofile[i] == NULL) {
2867497Sroot 			u.u_r.r_val1 = i;
2877497Sroot 			u.u_pofile[i] = 0;
288*21101Skarels 			if (i > u.u_lastfile)
289*21101Skarels 				u.u_lastfile = i;
2907497Sroot 			return (i);
2917497Sroot 		}
2927497Sroot 	u.u_error = EMFILE;
2937497Sroot 	return (-1);
2947497Sroot }
2957497Sroot 
29612748Ssam ufavail()
29712748Ssam {
29812748Ssam 	register int i, avail = 0;
29912748Ssam 
30012748Ssam 	for (i = 0; i < NOFILE; i++)
30112748Ssam 		if (u.u_ofile[i] == NULL)
30212748Ssam 			avail++;
30312748Ssam 	return (avail);
30412748Ssam }
30512748Ssam 
3067497Sroot struct	file *lastf;
3077497Sroot /*
3087497Sroot  * Allocate a user file descriptor
3097497Sroot  * and a file structure.
3107497Sroot  * Initialize the descriptor
3117497Sroot  * to point at the file structure.
3127497Sroot  */
3137497Sroot struct file *
3147497Sroot falloc()
3157497Sroot {
3167422Sroot 	register struct file *fp;
3177497Sroot 	register i;
3187422Sroot 
31912748Ssam 	i = ufalloc(0);
3207497Sroot 	if (i < 0)
3217497Sroot 		return (NULL);
3227497Sroot 	if (lastf == 0)
3237497Sroot 		lastf = file;
3247497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
3257497Sroot 		if (fp->f_count == 0)
3267497Sroot 			goto slot;
3277497Sroot 	for (fp = file; fp < lastf; fp++)
3287497Sroot 		if (fp->f_count == 0)
3297497Sroot 			goto slot;
3307497Sroot 	tablefull("file");
3317497Sroot 	u.u_error = ENFILE;
3327497Sroot 	return (NULL);
3337497Sroot slot:
3347497Sroot 	u.u_ofile[i] = fp;
33512748Ssam 	fp->f_count = 1;
33612748Ssam 	fp->f_data = 0;
3377497Sroot 	fp->f_offset = 0;
3387497Sroot 	lastf = fp + 1;
3397497Sroot 	return (fp);
3407497Sroot }
34112748Ssam 
3427497Sroot /*
3437497Sroot  * Convert a user supplied file descriptor into a pointer
3447497Sroot  * to a file structure.  Only task is to check range of the descriptor.
34512748Ssam  * Critical paths should use the GETF macro.
3467497Sroot  */
3477497Sroot struct file *
3487497Sroot getf(f)
3497497Sroot 	register int f;
3507497Sroot {
3517497Sroot 	register struct file *fp;
3527497Sroot 
3537497Sroot 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
3547497Sroot 		u.u_error = EBADF;
3557497Sroot 		return (NULL);
3567497Sroot 	}
3577497Sroot 	return (fp);
3587497Sroot }
3597497Sroot 
3607497Sroot /*
3617497Sroot  * Internal form of close.
36212748Ssam  * Decrement reference count on file structure.
36312748Ssam  * If last reference not going away, but no more
36412748Ssam  * references except in message queues, run a
36512748Ssam  * garbage collect.  This would better be done by
36612748Ssam  * forcing a gc() to happen sometime soon, rather
36712748Ssam  * than running one each time.
3687497Sroot  */
36913044Ssam closef(fp)
3707497Sroot 	register struct file *fp;
3717497Sroot {
3727497Sroot 
3737422Sroot 	if (fp == NULL)
3747422Sroot 		return;
3757497Sroot 	if (fp->f_count > 1) {
3767497Sroot 		fp->f_count--;
37712748Ssam 		if (fp->f_count == fp->f_msgcount)
37812748Ssam 			unp_gc();
3797422Sroot 		return;
3807422Sroot 	}
38113044Ssam 	(*fp->f_ops->fo_close)(fp);
3827497Sroot 	fp->f_count = 0;
3837422Sroot }
38413044Ssam 
38513044Ssam /*
38613044Ssam  * Apply an advisory lock on a file descriptor.
38713044Ssam  */
38813044Ssam flock()
38913044Ssam {
39013044Ssam 	register struct a {
39113044Ssam 		int	fd;
39213044Ssam 		int	how;
39313044Ssam 	} *uap = (struct a *)u.u_ap;
39413044Ssam 	register struct file *fp;
39513044Ssam 
39617003Smckusick 	GETF(fp, uap->fd);
39713101Ssam 	if (fp->f_type != DTYPE_INODE) {
39813101Ssam 		u.u_error = EOPNOTSUPP;
39913044Ssam 		return;
40013044Ssam 	}
40113101Ssam 	if (uap->how & LOCK_UN) {
40213101Ssam 		ino_unlock(fp, FSHLOCK|FEXLOCK);
40313044Ssam 		return;
40413044Ssam 	}
40517434Skarels 	if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
40617434Skarels 		return;					/* error? */
40717998Skarels 	if (uap->how & LOCK_EX)
40817998Skarels 		uap->how &= ~LOCK_SH;
40913101Ssam 	/* avoid work... */
41017998Skarels 	if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
41117998Skarels 	    (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
41213044Ssam 		return;
41313101Ssam 	u.u_error = ino_lock(fp, uap->how);
41413044Ssam }
415