xref: /csrg-svn/sys/kern/kern_descrip.c (revision 40873)
123367Smckusick /*
237728Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337728Smckusick  * All rights reserved.
423367Smckusick  *
537728Smckusick  * Redistribution and use in source and binary forms are permitted
637728Smckusick  * provided that the above copyright notice and this paragraph are
737728Smckusick  * duplicated in all such forms and that any documentation,
837728Smckusick  * advertising materials, and other materials related to such
937728Smckusick  * distribution and use acknowledge that the software was developed
1037728Smckusick  * by the University of California, Berkeley.  The name of the
1137728Smckusick  * University may not be used to endorse or promote products derived
1237728Smckusick  * from this software without specific prior written permission.
1337728Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437728Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537728Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637728Smckusick  *
17*40873Sbostic  *	@(#)kern_descrip.c	7.10 (Berkeley) 04/10/90
1823367Smckusick  */
197422Sroot 
2017089Sbloom #include "param.h"
2117089Sbloom #include "systm.h"
2237728Smckusick #include "syscontext.h"
2317089Sbloom #include "kernel.h"
2437728Smckusick #include "vnode.h"
2517089Sbloom #include "proc.h"
2617089Sbloom #include "file.h"
2717089Sbloom #include "socket.h"
2817089Sbloom #include "socketvar.h"
2917089Sbloom #include "mount.h"
3017089Sbloom #include "stat.h"
317422Sroot 
3217089Sbloom #include "ioctl.h"
337497Sroot 
347422Sroot /*
357497Sroot  * Descriptor management.
367422Sroot  */
377497Sroot 
387497Sroot /*
397497Sroot  * System calls on descriptors.
407497Sroot  */
418029Sroot getdtablesize()
427497Sroot {
437497Sroot 
447497Sroot 	u.u_r.r_val1 = NOFILE;
457497Sroot }
467497Sroot 
477422Sroot dup()
487422Sroot {
497497Sroot 	register struct a {
507497Sroot 		int	i;
517497Sroot 	} *uap = (struct a *) u.u_ap;
527696Ssam 	struct file *fp;
537696Ssam 	int j;
547497Sroot 
557497Sroot 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
567497Sroot 
5737728Smckusick 	if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
5837728Smckusick 		RETURN (EBADF);
5937728Smckusick 	if (u.u_error = ufalloc(0, &j))
607497Sroot 		return;
6137728Smckusick 	u.u_r.r_val1 = j;
6217435Skarels 	dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
637497Sroot }
647497Sroot 
657497Sroot dup2()
667497Sroot {
677422Sroot 	register struct a {
687497Sroot 		int	i, j;
697497Sroot 	} *uap = (struct a *) u.u_ap;
707497Sroot 	register struct file *fp;
7139354Smckusick 	int error;
727422Sroot 
7337728Smckusick 	if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
7437728Smckusick 		RETURN (EBADF);
7539354Smckusick 	if (uap->j < 0 || uap->j >= NOFILE)
7639354Smckusick 		RETURN (EBADF);
777497Sroot 	u.u_r.r_val1 = uap->j;
787497Sroot 	if (uap->i == uap->j)
7939354Smckusick 		RETURN (0);
807497Sroot 	if (u.u_ofile[uap->j]) {
818945Sroot 		if (u.u_pofile[uap->j] & UF_MAPPED)
828945Sroot 			munmapfd(uap->j);
8339354Smckusick 		error = closef(u.u_ofile[uap->j]);
847422Sroot 	}
8517435Skarels 	dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
8639354Smckusick 	/*
8739354Smckusick 	 * dup2() must succeed even though the close had an error.
8839354Smckusick 	 */
8939354Smckusick 	error = 0;		/* XXX */
9039354Smckusick 	RETURN (error);
917696Ssam }
927696Ssam 
9313101Ssam dupit(fd, fp, flags)
947696Ssam 	int fd;
957696Ssam 	register struct file *fp;
9613101Ssam 	register int flags;
977696Ssam {
987696Ssam 
997696Ssam 	u.u_ofile[fd] = fp;
10013101Ssam 	u.u_pofile[fd] = flags;
1017497Sroot 	fp->f_count++;
10221101Skarels 	if (fd > u.u_lastfile)
10321101Skarels 		u.u_lastfile = fd;
1047422Sroot }
1057422Sroot 
10612748Ssam /*
10712748Ssam  * The file control system call.
10812748Ssam  */
10912748Ssam fcntl()
1107497Sroot {
1117497Sroot 	register struct file *fp;
1127497Sroot 	register struct a {
11312748Ssam 		int	fdes;
11412748Ssam 		int	cmd;
11512748Ssam 		int	arg;
11637728Smckusick 	} *uap = (struct a *)u.u_ap;
11712748Ssam 	register char *pop;
11837728Smckusick 	int i;
1197497Sroot 
12037728Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
12137728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL)
12237728Smckusick 		RETURN (EBADF);
12312748Ssam 	pop = &u.u_pofile[uap->fdes];
12412748Ssam 	switch(uap->cmd) {
12515076Skarels 	case F_DUPFD:
12637728Smckusick 		if (uap->arg < 0 || uap->arg >= NOFILE) {
12712748Ssam 			u.u_error = EINVAL;
12812748Ssam 			return;
12912748Ssam 		}
13037728Smckusick 		if (u.u_error = ufalloc(uap->arg, &i))
13112748Ssam 			return;
13237728Smckusick 		u.u_r.r_val1 = i;
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:
19435810Smarc 		*valuep = ((struct socket *)fp->f_data)->so_pgid;
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 {
20837728Smckusick 
20912748Ssam 	if (fp->f_type == DTYPE_SOCKET) {
21035810Smarc 		((struct socket *)fp->f_data)->so_pgid = value;
21112748Ssam 		return (0);
21212748Ssam 	}
21312748Ssam 	if (value > 0) {
21412748Ssam 		struct proc *p = pfind(value);
21512748Ssam 		if (p == 0)
21628201Skarels 			return (ESRCH);
21735810Smarc 		value = p->p_pgrp->pg_id;
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 {
23537728Smckusick 		int	fdes;
23612748Ssam 	} *uap = (struct a *)u.u_ap;
23712748Ssam 	register struct file *fp;
23813044Ssam 	register u_char *pf;
2398029Sroot 
24037728Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
24137728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL)
24237728Smckusick 		RETURN (EBADF);
24337728Smckusick 	pf = (u_char *)&u.u_pofile[uap->fdes];
24413044Ssam 	if (*pf & UF_MAPPED)
24537728Smckusick 		munmapfd(uap->fdes);
24637728Smckusick 	u.u_ofile[uap->fdes] = NULL;
24721101Skarels 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
24821101Skarels 		u.u_lastfile--;
24915550Skarels 	*pf = 0;
25039354Smckusick 	RETURN (closef(fp));
2518029Sroot }
2528029Sroot 
25313044Ssam fstat()
25413044Ssam {
25513044Ssam 	register struct file *fp;
25613044Ssam 	register struct a {
25713044Ssam 		int	fdes;
25813044Ssam 		struct	stat *sb;
25937728Smckusick 	} *uap = (struct a *)u.u_ap;
26013044Ssam 	struct stat ub;
26113044Ssam 
26237728Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
26337728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL)
26437728Smckusick 		RETURN (EBADF);
26513044Ssam 	switch (fp->f_type) {
26613044Ssam 
26737728Smckusick 	case DTYPE_VNODE:
26837728Smckusick 		u.u_error = vn_stat((struct vnode *)fp->f_data, &ub);
26913044Ssam 		break;
27013044Ssam 
27113044Ssam 	case DTYPE_SOCKET:
27213044Ssam 		u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
27313044Ssam 		break;
27413044Ssam 
27513044Ssam 	default:
27613044Ssam 		panic("fstat");
27713044Ssam 		/*NOTREACHED*/
27813044Ssam 	}
27913044Ssam 	if (u.u_error == 0)
28013101Ssam 		u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
28113101Ssam 		    sizeof (ub));
28213044Ssam }
28313044Ssam 
2847422Sroot /*
2857497Sroot  * Allocate a user file descriptor.
2867422Sroot  */
28737728Smckusick ufalloc(want, result)
28837728Smckusick 	register int want;
28937728Smckusick 	int *result;
2907422Sroot {
2917497Sroot 
29239733Smckusick 	for (; want < NOFILE; want++) {
29337728Smckusick 		if (u.u_ofile[want] == NULL) {
29437728Smckusick 			u.u_pofile[want] = 0;
29537728Smckusick 			if (want > u.u_lastfile)
29637728Smckusick 				u.u_lastfile = want;
29739733Smckusick 			*result = want;
29837728Smckusick 			return (0);
2997497Sroot 		}
30039733Smckusick 	}
30137728Smckusick 	return (EMFILE);
3027497Sroot }
3037497Sroot 
30412748Ssam ufavail()
30512748Ssam {
30612748Ssam 	register int i, avail = 0;
30712748Ssam 
30812748Ssam 	for (i = 0; i < NOFILE; i++)
30912748Ssam 		if (u.u_ofile[i] == NULL)
31012748Ssam 			avail++;
31112748Ssam 	return (avail);
31212748Ssam }
31312748Ssam 
3147497Sroot struct	file *lastf;
3157497Sroot /*
3167497Sroot  * Allocate a user file descriptor
3177497Sroot  * and a file structure.
3187497Sroot  * Initialize the descriptor
3197497Sroot  * to point at the file structure.
3207497Sroot  */
32137728Smckusick falloc(resultfp, resultfd)
32237728Smckusick 	struct file **resultfp;
32337728Smckusick 	int *resultfd;
3247497Sroot {
3257422Sroot 	register struct file *fp;
32637728Smckusick 	int error, i;
3277422Sroot 
32837728Smckusick 	if (error = ufalloc(0, &i))
32937728Smckusick 		return (error);
3307497Sroot 	if (lastf == 0)
3317497Sroot 		lastf = file;
3327497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
3337497Sroot 		if (fp->f_count == 0)
3347497Sroot 			goto slot;
3357497Sroot 	for (fp = file; fp < lastf; fp++)
3367497Sroot 		if (fp->f_count == 0)
3377497Sroot 			goto slot;
3387497Sroot 	tablefull("file");
33937728Smckusick 	return (ENFILE);
3407497Sroot slot:
3417497Sroot 	u.u_ofile[i] = fp;
34212748Ssam 	fp->f_count = 1;
34312748Ssam 	fp->f_data = 0;
3447497Sroot 	fp->f_offset = 0;
34537728Smckusick 	fp->f_cred = u.u_cred;
34637728Smckusick 	crhold(fp->f_cred);
3477497Sroot 	lastf = fp + 1;
34837728Smckusick 	if (resultfp)
34937728Smckusick 		*resultfp = fp;
35037728Smckusick 	if (resultfd)
35137728Smckusick 		*resultfd = i;
35237728Smckusick 	return (0);
3537497Sroot }
35412748Ssam 
3557497Sroot /*
3567497Sroot  * Internal form of close.
35712748Ssam  * Decrement reference count on file structure.
3587497Sroot  */
35913044Ssam closef(fp)
3607497Sroot 	register struct file *fp;
3617497Sroot {
36239354Smckusick 	int error;
3637497Sroot 
3647422Sroot 	if (fp == NULL)
36539354Smckusick 		return (0);
3667497Sroot 	if (fp->f_count > 1) {
3677497Sroot 		fp->f_count--;
36839354Smckusick 		return (0);
3697422Sroot 	}
37037728Smckusick 	if (fp->f_count < 1)
37137728Smckusick 		panic("closef: count < 1");
37239354Smckusick 	error = (*fp->f_ops->fo_close)(fp);
37337728Smckusick 	crfree(fp->f_cred);
3747497Sroot 	fp->f_count = 0;
37539354Smckusick 	return (error);
3767422Sroot }
37713044Ssam 
37813044Ssam /*
37913044Ssam  * Apply an advisory lock on a file descriptor.
38013044Ssam  */
38113044Ssam flock()
38213044Ssam {
38313044Ssam 	register struct a {
38437728Smckusick 		int	fdes;
38513044Ssam 		int	how;
38613044Ssam 	} *uap = (struct a *)u.u_ap;
38713044Ssam 	register struct file *fp;
38813044Ssam 
38937728Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
39037728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL)
39137728Smckusick 		RETURN (EBADF);
39237728Smckusick 	if (fp->f_type != DTYPE_VNODE) {
39313101Ssam 		u.u_error = EOPNOTSUPP;
39413044Ssam 		return;
39513044Ssam 	}
39613101Ssam 	if (uap->how & LOCK_UN) {
39737728Smckusick 		vn_unlock(fp, FSHLOCK|FEXLOCK);
39813044Ssam 		return;
39913044Ssam 	}
40017434Skarels 	if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
40117434Skarels 		return;					/* error? */
40217998Skarels 	if (uap->how & LOCK_EX)
40317998Skarels 		uap->how &= ~LOCK_SH;
40413101Ssam 	/* avoid work... */
40517998Skarels 	if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
40617998Skarels 	    (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
40713044Ssam 		return;
40837728Smckusick 	u.u_error = vn_lock(fp, uap->how);
40913044Ssam }
41037586Smarc 
41137586Smarc /*
41237586Smarc  * File Descriptor pseudo-device driver (/dev/fd/).
41337586Smarc  *
41437586Smarc  * Fred Blonder - U of Maryland	11-Sep-1984
41537586Smarc  *
41637586Smarc  * Opening minor device N dup()s the file (if any) connected to file
41737586Smarc  * descriptor N belonging to the calling process.  Note that this driver
41837586Smarc  * consists of only the ``open()'' routine, because all subsequent
41937586Smarc  * references to this file will be direct to the other driver.
42037586Smarc  */
42137728Smckusick /* ARGSUSED */
42237728Smckusick fdopen(dev, mode, type)
42337586Smarc 	dev_t dev;
42437728Smckusick 	int mode, type;
42537586Smarc {
42637586Smarc 	struct file *fp, *wfp;
427*40873Sbostic 	int indx, dfd;
42837586Smarc 
42937586Smarc 	/*
430*40873Sbostic 	 * XXX
431*40873Sbostic 	 * Horrid kludge: u.u_r.r_val1 contains the value of the new file
432*40873Sbostic 	 * descriptor, which was set before the call to vn_open() by copen()
433*40873Sbostic 	 * in vfs_syscalls.c.
43437586Smarc 	 */
435*40873Sbostic 	indx = u.u_r.r_val1;
436*40873Sbostic 	fp = u.u_ofile[indx];
437*40873Sbostic 
43837586Smarc 	/*
439*40873Sbostic 	 * File system device minor number is the to-be-dup'd fd number.
440*40873Sbostic 	 * If it is greater than the allowed number of file descriptors,
441*40873Sbostic 	 * or the fd to be dup'd has already been closed, reject.  Note,
442*40873Sbostic  	 * check for new == old is necessary as u_falloc could allocate
443*40873Sbostic 	 * an already closed to-be-dup'd descriptor as the new descriptor.
44437586Smarc 	 */
445*40873Sbostic 	dfd = minor(dev);
446*40873Sbostic 	if ((u_int)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL ||
447*40873Sbostic 	    fp == wfp)
44837586Smarc 		return (EBADF);
449*40873Sbostic 
45037586Smarc 	/*
451*40873Sbostic 	 * Check that the mode the file is being opened for is a subset
452*40873Sbostic 	 * of the mode of the existing descriptor.
45337586Smarc 	 */
454*40873Sbostic 	if ((mode & (FREAD|FWRITE) | wfp->f_flag) != wfp->f_flag)
45537586Smarc 		return (EACCES);
45637728Smckusick 	dupit(indx, wfp, u.u_pofile[dfd]);
457*40873Sbostic 
45839498Smckusick 	/*
459*40873Sbostic 	 * Delete references to this pseudo-device by returning a special
460*40873Sbostic 	 * error (EJUSTRETURN) that will cause all resources to be freed,
461*40873Sbostic 	 * then detected and cleared by copen().
46239498Smckusick 	 */
46340704Skarels 	return (EJUSTRETURN);			/* XXX */
46437586Smarc }
465