xref: /csrg-svn/sys/kern/kern_descrip.c (revision 28201)
123367Smckusick /*
223367Smckusick  * Copyright (c) 1982 Regents of the University of California.
323367Smckusick  * All rights reserved.  The Berkeley software License Agreement
423367Smckusick  * specifies the terms and conditions for redistribution.
523367Smckusick  *
6*28201Skarels  *	@(#)kern_descrip.c	6.13 (Berkeley) 05/15/86
723367Smckusick  */
87422Sroot 
917089Sbloom #include "param.h"
1017089Sbloom #include "systm.h"
1117089Sbloom #include "dir.h"
1217089Sbloom #include "user.h"
1317089Sbloom #include "kernel.h"
1417089Sbloom #include "inode.h"
1517089Sbloom #include "proc.h"
1617089Sbloom #include "file.h"
1717089Sbloom #include "socket.h"
1817089Sbloom #include "socketvar.h"
1917089Sbloom #include "mount.h"
2017089Sbloom #include "stat.h"
217422Sroot 
2217089Sbloom #include "ioctl.h"
237497Sroot 
247422Sroot /*
257497Sroot  * Descriptor management.
267422Sroot  */
277497Sroot 
287497Sroot /*
297497Sroot  * TODO:
3012748Ssam  *	eliminate u.u_error side effects
317497Sroot  */
327497Sroot 
337497Sroot /*
347497Sroot  * System calls on descriptors.
357497Sroot  */
368029Sroot getdtablesize()
377497Sroot {
387497Sroot 
397497Sroot 	u.u_r.r_val1 = NOFILE;
407497Sroot }
417497Sroot 
428098Sroot getdopt()
438098Sroot {
448098Sroot 
458098Sroot }
468098Sroot 
478098Sroot setdopt()
488098Sroot {
498098Sroot 
508098Sroot }
518098Sroot 
527422Sroot dup()
537422Sroot {
547497Sroot 	register struct a {
557497Sroot 		int	i;
567497Sroot 	} *uap = (struct a *) u.u_ap;
577696Ssam 	struct file *fp;
587696Ssam 	int j;
597497Sroot 
607497Sroot 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
617497Sroot 
6217003Smckusick 	GETF(fp, uap->i);
6312748Ssam 	j = ufalloc(0);
647497Sroot 	if (j < 0)
657497Sroot 		return;
6617435Skarels 	dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
677497Sroot }
687497Sroot 
697497Sroot dup2()
707497Sroot {
717422Sroot 	register struct a {
727497Sroot 		int	i, j;
737497Sroot 	} *uap = (struct a *) u.u_ap;
747497Sroot 	register struct file *fp;
757422Sroot 
7617003Smckusick 	GETF(fp, uap->i);
777497Sroot 	if (uap->j < 0 || uap->j >= NOFILE) {
787497Sroot 		u.u_error = EBADF;
797497Sroot 		return;
807422Sroot 	}
817497Sroot 	u.u_r.r_val1 = uap->j;
827497Sroot 	if (uap->i == uap->j)
837497Sroot 		return;
847497Sroot 	if (u.u_ofile[uap->j]) {
858945Sroot 		if (u.u_pofile[uap->j] & UF_MAPPED)
868945Sroot 			munmapfd(uap->j);
8713101Ssam 		closef(u.u_ofile[uap->j]);
887422Sroot 		if (u.u_error)
897422Sroot 			return;
907422Sroot 	}
9117435Skarels 	dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
927696Ssam }
937696Ssam 
9413101Ssam dupit(fd, fp, flags)
957696Ssam 	int fd;
967696Ssam 	register struct file *fp;
9713101Ssam 	register int flags;
987696Ssam {
997696Ssam 
1007696Ssam 	u.u_ofile[fd] = fp;
10113101Ssam 	u.u_pofile[fd] = flags;
1027497Sroot 	fp->f_count++;
10321101Skarels 	if (fd > u.u_lastfile)
10421101Skarels 		u.u_lastfile = fd;
1057422Sroot }
1067422Sroot 
10712748Ssam /*
10812748Ssam  * The file control system call.
10912748Ssam  */
11012748Ssam fcntl()
1117497Sroot {
1127497Sroot 	register struct file *fp;
1137497Sroot 	register struct a {
11412748Ssam 		int	fdes;
11512748Ssam 		int	cmd;
11612748Ssam 		int	arg;
11712748Ssam 	} *uap;
11812748Ssam 	register i;
11912748Ssam 	register char *pop;
1207497Sroot 
12112748Ssam 	uap = (struct a *)u.u_ap;
12217003Smckusick 	GETF(fp, uap->fdes);
12312748Ssam 	pop = &u.u_pofile[uap->fdes];
12412748Ssam 	switch(uap->cmd) {
12515076Skarels 	case F_DUPFD:
12612748Ssam 		i = uap->arg;
12717434Skarels 		if (i < 0 || i >= NOFILE) {
12812748Ssam 			u.u_error = EINVAL;
12912748Ssam 			return;
13012748Ssam 		}
13112748Ssam 		if ((i = ufalloc(i)) < 0)
13212748Ssam 			return;
13317435Skarels 		dupit(i, fp, *pop &~ UF_EXCLOSE);
13412748Ssam 		break;
1357497Sroot 
13615076Skarels 	case F_GETFD:
13712748Ssam 		u.u_r.r_val1 = *pop & 1;
13812748Ssam 		break;
1397422Sroot 
14015076Skarels 	case F_SETFD:
14112748Ssam 		*pop = (*pop &~ 1) | (uap->arg & 1);
14212748Ssam 		break;
1438145Sroot 
14415076Skarels 	case F_GETFL:
14512748Ssam 		u.u_r.r_val1 = fp->f_flag+FOPEN;
14612748Ssam 		break;
1478145Sroot 
14815076Skarels 	case F_SETFL:
14912748Ssam 		fp->f_flag &= FCNTLCANT;
15012748Ssam 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
15112748Ssam 		u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
1529995Ssam 		if (u.u_error)
15312748Ssam 			break;
15412748Ssam 		u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
15512748Ssam 		if (u.u_error)
15612748Ssam 			(void) fset(fp, FNDELAY, 0);
15712748Ssam 		break;
1587422Sroot 
15915076Skarels 	case F_GETOWN:
16015076Skarels 		u.u_error = fgetown(fp, &u.u_r.r_val1);
16112748Ssam 		break;
1627422Sroot 
16315076Skarels 	case F_SETOWN:
16415076Skarels 		u.u_error = fsetown(fp, uap->arg);
1657422Sroot 		break;
1668115Sroot 
16712748Ssam 	default:
16812748Ssam 		u.u_error = EINVAL;
1697422Sroot 	}
1707422Sroot }
1717422Sroot 
17212748Ssam fset(fp, bit, value)
17312748Ssam 	struct file *fp;
17412748Ssam 	int bit, value;
1757422Sroot {
1767422Sroot 
17712748Ssam 	if (value)
17812748Ssam 		fp->f_flag |= bit;
17912748Ssam 	else
18012748Ssam 		fp->f_flag &= ~bit;
18112748Ssam 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
18212748Ssam 	    (caddr_t)&value));
18312748Ssam }
1847422Sroot 
18512748Ssam fgetown(fp, valuep)
18612748Ssam 	struct file *fp;
18712748Ssam 	int *valuep;
18812748Ssam {
18912748Ssam 	int error;
1908115Sroot 
19112748Ssam 	switch (fp->f_type) {
1928115Sroot 
19312748Ssam 	case DTYPE_SOCKET:
19412748Ssam 		*valuep = ((struct socket *)fp->f_data)->so_pgrp;
19512748Ssam 		return (0);
1967497Sroot 
19712748Ssam 	default:
19812748Ssam 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
19912748Ssam 		*valuep = -*valuep;
20012748Ssam 		return (error);
2017422Sroot 	}
2027422Sroot }
2037422Sroot 
20412748Ssam fsetown(fp, value)
20512748Ssam 	struct file *fp;
20612748Ssam 	int value;
2077422Sroot {
2087422Sroot 
20912748Ssam 	if (fp->f_type == DTYPE_SOCKET) {
21012748Ssam 		((struct socket *)fp->f_data)->so_pgrp = value;
21112748Ssam 		return (0);
21212748Ssam 	}
21312748Ssam 	if (value > 0) {
21412748Ssam 		struct proc *p = pfind(value);
21512748Ssam 		if (p == 0)
216*28201Skarels 			return (ESRCH);
21712748Ssam 		value = p->p_pgrp;
21812748Ssam 	} else
21912748Ssam 		value = -value;
22012748Ssam 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
2217422Sroot }
2227422Sroot 
22312748Ssam fioctl(fp, cmd, value)
22412748Ssam 	struct file *fp;
22512748Ssam 	int cmd;
22612748Ssam 	caddr_t value;
2277422Sroot {
2287422Sroot 
22912748Ssam 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
2307422Sroot }
2317422Sroot 
23212748Ssam close()
2338029Sroot {
23421101Skarels 	struct a {
23512748Ssam 		int	i;
23612748Ssam 	} *uap = (struct a *)u.u_ap;
23721101Skarels 	register int i = uap->i;
23812748Ssam 	register struct file *fp;
23913044Ssam 	register u_char *pf;
2408029Sroot 
24121101Skarels 	GETF(fp, i);
24221101Skarels 	pf = (u_char *)&u.u_pofile[i];
24313044Ssam 	if (*pf & UF_MAPPED)
24421101Skarels 		munmapfd(i);
24521101Skarels 	u.u_ofile[i] = NULL;
24621101Skarels 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
24721101Skarels 		u.u_lastfile--;
24815550Skarels 	*pf = 0;
24913044Ssam 	closef(fp);
25012748Ssam 	/* WHAT IF u.u_error ? */
2518029Sroot }
2528029Sroot 
25313044Ssam fstat()
25413044Ssam {
25513044Ssam 	register struct file *fp;
25613044Ssam 	register struct a {
25713044Ssam 		int	fdes;
25813044Ssam 		struct	stat *sb;
25913044Ssam 	} *uap;
26013044Ssam 	struct stat ub;
26113044Ssam 
26213044Ssam 	uap = (struct a *)u.u_ap;
26317003Smckusick 	GETF(fp, uap->fdes);
26413044Ssam 	switch (fp->f_type) {
26513044Ssam 
26613044Ssam 	case DTYPE_INODE:
26713044Ssam 		u.u_error = ino_stat((struct inode *)fp->f_data, &ub);
26813044Ssam 		break;
26913044Ssam 
27013044Ssam 	case DTYPE_SOCKET:
27113044Ssam 		u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
27213044Ssam 		break;
27313044Ssam 
27413044Ssam 	default:
27513044Ssam 		panic("fstat");
27613044Ssam 		/*NOTREACHED*/
27713044Ssam 	}
27813044Ssam 	if (u.u_error == 0)
27913101Ssam 		u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
28013101Ssam 		    sizeof (ub));
28113044Ssam }
28213044Ssam 
2837422Sroot /*
2847497Sroot  * Allocate a user file descriptor.
2857422Sroot  */
28612748Ssam ufalloc(i)
28712748Ssam 	register int i;
2887422Sroot {
2897497Sroot 
29012748Ssam 	for (; i < NOFILE; i++)
2917497Sroot 		if (u.u_ofile[i] == NULL) {
2927497Sroot 			u.u_r.r_val1 = i;
2937497Sroot 			u.u_pofile[i] = 0;
29421101Skarels 			if (i > u.u_lastfile)
29521101Skarels 				u.u_lastfile = i;
2967497Sroot 			return (i);
2977497Sroot 		}
2987497Sroot 	u.u_error = EMFILE;
2997497Sroot 	return (-1);
3007497Sroot }
3017497Sroot 
30212748Ssam ufavail()
30312748Ssam {
30412748Ssam 	register int i, avail = 0;
30512748Ssam 
30612748Ssam 	for (i = 0; i < NOFILE; i++)
30712748Ssam 		if (u.u_ofile[i] == NULL)
30812748Ssam 			avail++;
30912748Ssam 	return (avail);
31012748Ssam }
31112748Ssam 
3127497Sroot struct	file *lastf;
3137497Sroot /*
3147497Sroot  * Allocate a user file descriptor
3157497Sroot  * and a file structure.
3167497Sroot  * Initialize the descriptor
3177497Sroot  * to point at the file structure.
3187497Sroot  */
3197497Sroot struct file *
3207497Sroot falloc()
3217497Sroot {
3227422Sroot 	register struct file *fp;
3237497Sroot 	register i;
3247422Sroot 
32512748Ssam 	i = ufalloc(0);
3267497Sroot 	if (i < 0)
3277497Sroot 		return (NULL);
3287497Sroot 	if (lastf == 0)
3297497Sroot 		lastf = file;
3307497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
3317497Sroot 		if (fp->f_count == 0)
3327497Sroot 			goto slot;
3337497Sroot 	for (fp = file; fp < lastf; fp++)
3347497Sroot 		if (fp->f_count == 0)
3357497Sroot 			goto slot;
3367497Sroot 	tablefull("file");
3377497Sroot 	u.u_error = ENFILE;
3387497Sroot 	return (NULL);
3397497Sroot slot:
3407497Sroot 	u.u_ofile[i] = fp;
34112748Ssam 	fp->f_count = 1;
34212748Ssam 	fp->f_data = 0;
3437497Sroot 	fp->f_offset = 0;
3447497Sroot 	lastf = fp + 1;
3457497Sroot 	return (fp);
3467497Sroot }
34712748Ssam 
3487497Sroot /*
3497497Sroot  * Convert a user supplied file descriptor into a pointer
3507497Sroot  * to a file structure.  Only task is to check range of the descriptor.
35112748Ssam  * Critical paths should use the GETF macro.
3527497Sroot  */
3537497Sroot struct file *
3547497Sroot getf(f)
3557497Sroot 	register int f;
3567497Sroot {
3577497Sroot 	register struct file *fp;
3587497Sroot 
3597497Sroot 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
3607497Sroot 		u.u_error = EBADF;
3617497Sroot 		return (NULL);
3627497Sroot 	}
3637497Sroot 	return (fp);
3647497Sroot }
3657497Sroot 
3667497Sroot /*
3677497Sroot  * Internal form of close.
36812748Ssam  * Decrement reference count on file structure.
3697497Sroot  */
37013044Ssam closef(fp)
3717497Sroot 	register struct file *fp;
3727497Sroot {
3737497Sroot 
3747422Sroot 	if (fp == NULL)
3757422Sroot 		return;
3767497Sroot 	if (fp->f_count > 1) {
3777497Sroot 		fp->f_count--;
3787422Sroot 		return;
3797422Sroot 	}
38013044Ssam 	(*fp->f_ops->fo_close)(fp);
3817497Sroot 	fp->f_count = 0;
3827422Sroot }
38313044Ssam 
38413044Ssam /*
38513044Ssam  * Apply an advisory lock on a file descriptor.
38613044Ssam  */
38713044Ssam flock()
38813044Ssam {
38913044Ssam 	register struct a {
39013044Ssam 		int	fd;
39113044Ssam 		int	how;
39213044Ssam 	} *uap = (struct a *)u.u_ap;
39313044Ssam 	register struct file *fp;
39413044Ssam 
39517003Smckusick 	GETF(fp, uap->fd);
39613101Ssam 	if (fp->f_type != DTYPE_INODE) {
39713101Ssam 		u.u_error = EOPNOTSUPP;
39813044Ssam 		return;
39913044Ssam 	}
40013101Ssam 	if (uap->how & LOCK_UN) {
40113101Ssam 		ino_unlock(fp, FSHLOCK|FEXLOCK);
40213044Ssam 		return;
40313044Ssam 	}
40417434Skarels 	if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
40517434Skarels 		return;					/* error? */
40617998Skarels 	if (uap->how & LOCK_EX)
40717998Skarels 		uap->how &= ~LOCK_SH;
40813101Ssam 	/* avoid work... */
40917998Skarels 	if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
41017998Skarels 	    (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
41113044Ssam 		return;
41213101Ssam 	u.u_error = ino_lock(fp, uap->how);
41313044Ssam }
414