xref: /csrg-svn/sys/kern/kern_descrip.c (revision 13044)
1*13044Ssam /*	kern_descrip.c	5.25	83/06/12	*/
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/socket.h"
137422Sroot #include "../h/socketvar.h"
147497Sroot #include "../h/mount.h"
15*13044Ssam #include "../h/stat.h"
167422Sroot 
1712748Ssam #include "../h/ioctl.h"
187497Sroot 
197422Sroot /*
207497Sroot  * Descriptor management.
217422Sroot  */
227497Sroot 
237497Sroot /*
247497Sroot  * TODO:
2512748Ssam  *	increase NOFILE
2612748Ssam  *	eliminate u.u_error side effects
277497Sroot  */
287497Sroot 
297497Sroot /*
307497Sroot  * System calls on descriptors.
317497Sroot  */
328029Sroot getdtablesize()
337497Sroot {
347497Sroot 
357497Sroot 	u.u_r.r_val1 = NOFILE;
367497Sroot }
377497Sroot 
388098Sroot getdopt()
398098Sroot {
408098Sroot 
418098Sroot }
428098Sroot 
438098Sroot setdopt()
448098Sroot {
458098Sroot 
468098Sroot }
478098Sroot 
487422Sroot dup()
497422Sroot {
507497Sroot 	register struct a {
517497Sroot 		int	i;
527497Sroot 	} *uap = (struct a *) u.u_ap;
537696Ssam 	struct file *fp;
547696Ssam 	int j;
557497Sroot 
567497Sroot 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
577497Sroot 
587497Sroot 	fp = getf(uap->i);
597497Sroot 	if (fp == 0)
607497Sroot 		return;
6112748Ssam 	j = ufalloc(0);
627497Sroot 	if (j < 0)
637497Sroot 		return;
6412748Ssam 	dupit(j, fp, u.u_pofile[uap->i]);
657497Sroot }
667497Sroot 
677497Sroot dup2()
687497Sroot {
697422Sroot 	register struct a {
707497Sroot 		int	i, j;
717497Sroot 	} *uap = (struct a *) u.u_ap;
727497Sroot 	register struct file *fp;
737422Sroot 
747497Sroot 	fp = getf(uap->i);
757497Sroot 	if (fp == 0)
767422Sroot 		return;
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);
8712748Ssam 		closef(u.u_ofile[uap->j], u.u_pofile[uap->j]);
887422Sroot 		if (u.u_error)
897422Sroot 			return;
907497Sroot 		/* u.u_ofile[uap->j] = 0; */
917696Ssam 		/* u.u_pofile[uap->j] = 0; */
927422Sroot 	}
9312748Ssam 	dupit(uap->j, fp, u.u_pofile[uap->i]);
947696Ssam }
957696Ssam 
967696Ssam dupit(fd, fp, lockflags)
977696Ssam 	int fd;
987696Ssam 	register struct file *fp;
997696Ssam 	register int lockflags;
1007696Ssam {
1017696Ssam 
1027696Ssam 	u.u_ofile[fd] = fp;
1037696Ssam 	u.u_pofile[fd] = lockflags;
1047497Sroot 	fp->f_count++;
10512748Ssam /* THIS DOESN'T BELONG HERE */
1069590Ssam 	if (lockflags&UF_SHLOCK)
10712748Ssam 		((struct inode *)fp->f_data)->i_shlockc++;
1089590Ssam 	if (lockflags&UF_EXLOCK)
10912748Ssam 		((struct inode *)fp->f_data)->i_exlockc++;
11012748Ssam /* END DOESN'T BELONG */
1117422Sroot }
1127422Sroot 
11312748Ssam /*
11412748Ssam  * The file control system call.
11512748Ssam  */
11612748Ssam fcntl()
1177497Sroot {
1187497Sroot 	register struct file *fp;
1197497Sroot 	register struct a {
12012748Ssam 		int	fdes;
12112748Ssam 		int	cmd;
12212748Ssam 		int	arg;
12312748Ssam 	} *uap;
12412748Ssam 	register i;
12512748Ssam 	register char *pop;
1267497Sroot 
12712748Ssam 	uap = (struct a *)u.u_ap;
12812748Ssam 	fp = getf(uap->fdes);
12912748Ssam 	if (fp == NULL)
1307497Sroot 		return;
13112748Ssam 	pop = &u.u_pofile[uap->fdes];
13212748Ssam 	switch(uap->cmd) {
13312748Ssam 	case 0:
13412748Ssam 		i = uap->arg;
13512748Ssam 		if (i < 0 || i > NOFILE) {
13612748Ssam 			u.u_error = EINVAL;
13712748Ssam 			return;
13812748Ssam 		}
13912748Ssam 		if ((i = ufalloc(i)) < 0)
14012748Ssam 			return;
14112748Ssam 		dupit(i, fp, *pop);
14212748Ssam 		break;
1437497Sroot 
14412748Ssam 	case 1:
14512748Ssam 		u.u_r.r_val1 = *pop & 1;
14612748Ssam 		break;
1477422Sroot 
14812748Ssam 	case 2:
14912748Ssam 		*pop = (*pop &~ 1) | (uap->arg & 1);
15012748Ssam 		break;
1518145Sroot 
15212748Ssam 	case 3:
15312748Ssam 		u.u_r.r_val1 = fp->f_flag+FOPEN;
15412748Ssam 		break;
1558145Sroot 
15612748Ssam 	case 4:
15712748Ssam 		fp->f_flag &= FCNTLCANT;
15812748Ssam 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
15912748Ssam 		u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
1609995Ssam 		if (u.u_error)
16112748Ssam 			break;
16212748Ssam 		u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
16312748Ssam 		if (u.u_error)
16412748Ssam 			(void) fset(fp, FNDELAY, 0);
16512748Ssam 		break;
1667422Sroot 
16712748Ssam 	case 5:
16812748Ssam 		u.u_error = fsetown(fp, uap->arg);
16912748Ssam 		break;
1707422Sroot 
17112748Ssam 	case 6:
17212748Ssam 		u.u_error = fgetown(fp, &u.u_r.r_val1);
1737422Sroot 		break;
1748115Sroot 
17512748Ssam 	default:
17612748Ssam 		u.u_error = EINVAL;
1777422Sroot 	}
1787422Sroot }
1797422Sroot 
18012748Ssam fset(fp, bit, value)
18112748Ssam 	struct file *fp;
18212748Ssam 	int bit, value;
1837422Sroot {
1847422Sroot 
18512748Ssam 	if (value)
18612748Ssam 		fp->f_flag |= bit;
18712748Ssam 	else
18812748Ssam 		fp->f_flag &= ~bit;
18912748Ssam 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
19012748Ssam 	    (caddr_t)&value));
19112748Ssam }
1927422Sroot 
19312748Ssam fgetown(fp, valuep)
19412748Ssam 	struct file *fp;
19512748Ssam 	int *valuep;
19612748Ssam {
19712748Ssam 	int error;
1988115Sroot 
19912748Ssam 	switch (fp->f_type) {
2008115Sroot 
20112748Ssam 	case DTYPE_SOCKET:
20212748Ssam 		*valuep = ((struct socket *)fp->f_data)->so_pgrp;
20312748Ssam 		return (0);
2047497Sroot 
20512748Ssam 	default:
20612748Ssam 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
20712748Ssam 		*valuep = -*valuep;
20812748Ssam 		return (error);
2097422Sroot 	}
2107422Sroot }
2117422Sroot 
21212748Ssam fsetown(fp, value)
21312748Ssam 	struct file *fp;
21412748Ssam 	int value;
2157422Sroot {
2167422Sroot 
21712748Ssam 	if (fp->f_type == DTYPE_SOCKET) {
21812748Ssam 		((struct socket *)fp->f_data)->so_pgrp = value;
21912748Ssam 		return (0);
22012748Ssam 	}
22112748Ssam 	if (value > 0) {
22212748Ssam 		struct proc *p = pfind(value);
22312748Ssam 		if (p == 0)
22412748Ssam 			return (EINVAL);
22512748Ssam 		value = p->p_pgrp;
22612748Ssam 	} else
22712748Ssam 		value = -value;
22812748Ssam 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
2297422Sroot }
2307422Sroot 
23112748Ssam fioctl(fp, cmd, value)
23212748Ssam 	struct file *fp;
23312748Ssam 	int cmd;
23412748Ssam 	caddr_t value;
2357422Sroot {
2367422Sroot 
23712748Ssam 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
2387422Sroot }
2397422Sroot 
24012748Ssam close()
2418029Sroot {
24212748Ssam 	register struct a {
24312748Ssam 		int	i;
24412748Ssam 	} *uap = (struct a *)u.u_ap;
24512748Ssam 	register struct file *fp;
246*13044Ssam 	register u_char *pf;
2478029Sroot 
24812748Ssam 	fp = getf(uap->i);
24912748Ssam 	if (fp == 0)
25012748Ssam 		return;
251*13044Ssam 	pf = (u_char *)&u.u_pofile[uap->i];
252*13044Ssam 	if (*pf & UF_MAPPED)
25312748Ssam 		munmapfd(uap->i);
254*13044Ssam 	if (*pf & (UF_SHLOCK|UF_EXLOCK))
255*13044Ssam 		unlockf(fp, pf);
256*13044Ssam 	closef(fp);
25712748Ssam 	/* WHAT IF u.u_error ? */
25812748Ssam 	u.u_ofile[uap->i] = NULL;
259*13044Ssam 	*pf = 0;
2608029Sroot }
2618029Sroot 
262*13044Ssam fstat()
263*13044Ssam {
264*13044Ssam 	register struct file *fp;
265*13044Ssam 	register struct a {
266*13044Ssam 		int	fdes;
267*13044Ssam 		struct	stat *sb;
268*13044Ssam 	} *uap;
269*13044Ssam 	struct stat ub;
270*13044Ssam 
271*13044Ssam 	uap = (struct a *)u.u_ap;
272*13044Ssam 	fp = getf(uap->fdes);
273*13044Ssam 	if (fp == 0)
274*13044Ssam 		return;
275*13044Ssam 	switch (fp->f_type) {
276*13044Ssam 
277*13044Ssam 	case DTYPE_INODE:
278*13044Ssam 		u.u_error = ino_stat((struct inode *)fp->f_data, &ub);
279*13044Ssam 		break;
280*13044Ssam 
281*13044Ssam 	case DTYPE_SOCKET:
282*13044Ssam 		u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
283*13044Ssam 		break;
284*13044Ssam 
285*13044Ssam 	default:
286*13044Ssam 		panic("fstat");
287*13044Ssam 		/*NOTREACHED*/
288*13044Ssam 	}
289*13044Ssam 	if (u.u_error == 0)
290*13044Ssam 		u.u_error = copyout(&ub, uap->sb, sizeof (ub));
291*13044Ssam }
292*13044Ssam 
2937422Sroot /*
2947497Sroot  * Allocate a user file descriptor.
2957422Sroot  */
29612748Ssam ufalloc(i)
29712748Ssam 	register int i;
2987422Sroot {
2997497Sroot 
30012748Ssam 	for (; i < NOFILE; i++)
3017497Sroot 		if (u.u_ofile[i] == NULL) {
3027497Sroot 			u.u_r.r_val1 = i;
3037497Sroot 			u.u_pofile[i] = 0;
3047497Sroot 			return (i);
3057497Sroot 		}
3067497Sroot 	u.u_error = EMFILE;
3077497Sroot 	return (-1);
3087497Sroot }
3097497Sroot 
31012748Ssam ufavail()
31112748Ssam {
31212748Ssam 	register int i, avail = 0;
31312748Ssam 
31412748Ssam 	for (i = 0; i < NOFILE; i++)
31512748Ssam 		if (u.u_ofile[i] == NULL)
31612748Ssam 			avail++;
31712748Ssam 	return (avail);
31812748Ssam }
31912748Ssam 
3207497Sroot struct	file *lastf;
3217497Sroot /*
3227497Sroot  * Allocate a user file descriptor
3237497Sroot  * and a file structure.
3247497Sroot  * Initialize the descriptor
3257497Sroot  * to point at the file structure.
3267497Sroot  */
3277497Sroot struct file *
3287497Sroot falloc()
3297497Sroot {
3307422Sroot 	register struct file *fp;
3317497Sroot 	register i;
3327422Sroot 
33312748Ssam 	i = ufalloc(0);
3347497Sroot 	if (i < 0)
3357497Sroot 		return (NULL);
3367497Sroot 	if (lastf == 0)
3377497Sroot 		lastf = file;
3387497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
3397497Sroot 		if (fp->f_count == 0)
3407497Sroot 			goto slot;
3417497Sroot 	for (fp = file; fp < lastf; fp++)
3427497Sroot 		if (fp->f_count == 0)
3437497Sroot 			goto slot;
3447497Sroot 	tablefull("file");
3457497Sroot 	u.u_error = ENFILE;
3467497Sroot 	return (NULL);
3477497Sroot slot:
3487497Sroot 	u.u_ofile[i] = fp;
34912748Ssam 	fp->f_count = 1;
35012748Ssam 	fp->f_data = 0;
3517497Sroot 	fp->f_offset = 0;
3527497Sroot 	lastf = fp + 1;
3537497Sroot 	return (fp);
3547497Sroot }
35512748Ssam 
3567497Sroot /*
3577497Sroot  * Convert a user supplied file descriptor into a pointer
3587497Sroot  * to a file structure.  Only task is to check range of the descriptor.
35912748Ssam  * Critical paths should use the GETF macro.
3607497Sroot  */
3617497Sroot struct file *
3627497Sroot getf(f)
3637497Sroot 	register int f;
3647497Sroot {
3657497Sroot 	register struct file *fp;
3667497Sroot 
3677497Sroot 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
3687497Sroot 		u.u_error = EBADF;
3697497Sroot 		return (NULL);
3707497Sroot 	}
3717497Sroot 	return (fp);
3727497Sroot }
3737497Sroot 
3747497Sroot /*
3757497Sroot  * Internal form of close.
37612748Ssam  * Decrement reference count on file structure.
37712748Ssam  * If last reference not going away, but no more
37812748Ssam  * references except in message queues, run a
37912748Ssam  * garbage collect.  This would better be done by
38012748Ssam  * forcing a gc() to happen sometime soon, rather
38112748Ssam  * than running one each time.
3827497Sroot  */
383*13044Ssam closef(fp)
3847497Sroot 	register struct file *fp;
3857497Sroot {
3867497Sroot 
3877422Sroot 	if (fp == NULL)
3887422Sroot 		return;
3897497Sroot 	if (fp->f_count > 1) {
3907497Sroot 		fp->f_count--;
39112748Ssam 		if (fp->f_count == fp->f_msgcount)
39212748Ssam 			unp_gc();
3937422Sroot 		return;
3947422Sroot 	}
395*13044Ssam 	(*fp->f_ops->fo_close)(fp);
3967497Sroot 	fp->f_count = 0;
3977422Sroot }
398*13044Ssam 
399*13044Ssam /*
400*13044Ssam  * Apply an advisory lock on a file descriptor.
401*13044Ssam  */
402*13044Ssam flock()
403*13044Ssam {
404*13044Ssam 	register struct a {
405*13044Ssam 		int	fd;
406*13044Ssam 		int	how;
407*13044Ssam 	} *uap = (struct a *)u.u_ap;
408*13044Ssam 	register struct file *fp;
409*13044Ssam 	register u_char *pf;
410*13044Ssam 	int cmd;
411*13044Ssam 
412*13044Ssam 	fp = getf(uap->fd);
413*13044Ssam 	if (fp == NULL)
414*13044Ssam 		return;
415*13044Ssam 	cmd = uap->how;
416*13044Ssam 	pf = (u_char *)&u.u_pofile[uap->fd];
417*13044Ssam 	if (cmd & LOCK_UN) {
418*13044Ssam 		unlockf(fp, pf);
419*13044Ssam 		return;
420*13044Ssam 	}
421*13044Ssam 	/*
422*13044Ssam 	 * No reason to write lock a file we've already
423*13044Ssam 	 * write locked, similarly with a read lock.
424*13044Ssam 	 */
425*13044Ssam 	if ((*pf & UF_EXLOCK) && (cmd & LOCK_EX) ||
426*13044Ssam 	    (*pf & UF_SHLOCK) && (cmd & LOCK_SH))
427*13044Ssam 		return;
428*13044Ssam 	switch (fp->f_type) {
429*13044Ssam 
430*13044Ssam 	case DTYPE_INODE:
431*13044Ssam 		u.u_error = ino_lock((struct inode *)fp->f_data, pf, cmd);
432*13044Ssam 		break;
433*13044Ssam 
434*13044Ssam 	case DTYPE_SOCKET:
435*13044Ssam 		u.u_error = soo_lock((struct socket *)fp->f_data, pf, cmd);
436*13044Ssam 		break;
437*13044Ssam 
438*13044Ssam 	default:
439*13044Ssam 		panic("lockf");
440*13044Ssam 	}
441*13044Ssam }
442*13044Ssam 
443*13044Ssam unlockf(fp, pf)
444*13044Ssam 	register struct file *fp;
445*13044Ssam 	register u_char *pf;
446*13044Ssam {
447*13044Ssam 
448*13044Ssam 	if ((*pf & (UF_SHLOCK|UF_EXLOCK)) == 0)
449*13044Ssam 		return;
450*13044Ssam 	switch (fp->f_type) {
451*13044Ssam 
452*13044Ssam 	case DTYPE_INODE:
453*13044Ssam 		ino_unlock((struct inode *)fp->f_data, *pf);
454*13044Ssam 		break;
455*13044Ssam 
456*13044Ssam 	case DTYPE_SOCKET:
457*13044Ssam 		soo_unlock((struct socket *)fp->f_data, *pf);
458*13044Ssam 		break;
459*13044Ssam 
460*13044Ssam 	default:
461*13044Ssam 		panic("unlockf");
462*13044Ssam 	}
463*13044Ssam 	*pf &= ~(UF_SHLOCK|UF_EXLOCK);
464*13044Ssam }
465