xref: /csrg-svn/sys/kern/kern_descrip.c (revision 7497)
1*7497Sroot /*	kern_descrip.c	5.2	82/07/24	*/
27422Sroot 
37422Sroot #include "../h/param.h"
47422Sroot #include "../h/systm.h"
57422Sroot #include "../h/dir.h"
67422Sroot #include "../h/user.h"
77422Sroot #include "../h/inode.h"
87422Sroot #include "../h/proc.h"
97422Sroot #include "../h/conf.h"
107422Sroot #include "../h/file.h"
117422Sroot #include "../h/inline.h"
127422Sroot #include "../h/socket.h"
137422Sroot #include "../h/socketvar.h"
14*7497Sroot #include "../h/mount.h"
157422Sroot 
16*7497Sroot #include "../h/descrip.h"
17*7497Sroot 
187422Sroot /*
19*7497Sroot  * Descriptor management.
207422Sroot  */
21*7497Sroot 
22*7497Sroot /*
23*7497Sroot  * TODO:
24*7497Sroot  *	getf should be renamed
25*7497Sroot  *	ufalloc side effects are gross
26*7497Sroot  */
27*7497Sroot 
28*7497Sroot /*
29*7497Sroot  * System calls on descriptors.
30*7497Sroot  */
31*7497Sroot dstd()
32*7497Sroot {
33*7497Sroot 
34*7497Sroot 	u.u_r.r_val1 = NOFILE;
35*7497Sroot }
36*7497Sroot 
377422Sroot dup()
387422Sroot {
39*7497Sroot 	register struct a {
40*7497Sroot 		int	i;
41*7497Sroot 	} *uap = (struct a *) u.u_ap;
427422Sroot 	register struct file *fp;
43*7497Sroot 	register int j;
44*7497Sroot 
45*7497Sroot 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
46*7497Sroot 
47*7497Sroot 	fp = getf(uap->i);
48*7497Sroot 	if (fp == 0)
49*7497Sroot 		return;
50*7497Sroot 	j = ufalloc();
51*7497Sroot 	if (j < 0)
52*7497Sroot 		return;
53*7497Sroot 	u.u_ofile[j] = fp;
54*7497Sroot 	fp->f_count++;
55*7497Sroot }
56*7497Sroot 
57*7497Sroot dup2()
58*7497Sroot {
597422Sroot 	register struct a {
60*7497Sroot 		int	i, j;
61*7497Sroot 	} *uap = (struct a *) u.u_ap;
62*7497Sroot 	register struct file *fp;
637422Sroot 
64*7497Sroot 	fp = getf(uap->i);
65*7497Sroot 	if (fp == 0)
667422Sroot 		return;
67*7497Sroot 	if (uap->j < 0 || uap->j >= NOFILE) {
68*7497Sroot 		u.u_error = EBADF;
69*7497Sroot 		return;
707422Sroot 	}
71*7497Sroot 	u.u_r.r_val1 = uap->j;
72*7497Sroot 	if (uap->i == uap->j)
73*7497Sroot 		return;
74*7497Sroot 	if (u.u_ofile[uap->j]) {
75*7497Sroot 		closef(u.u_ofile[uap->j], 0);
767422Sroot 		if (u.u_error)
777422Sroot 			return;
78*7497Sroot 		/* u.u_ofile[uap->j] = 0; */
797422Sroot 	}
80*7497Sroot 	u.u_ofile[uap->j] = fp;
81*7497Sroot 	fp->f_count++;
827422Sroot }
837422Sroot 
84*7497Sroot close()
85*7497Sroot {
86*7497Sroot 	register struct a {
87*7497Sroot 		int	i;
88*7497Sroot 	} *uap = (struct a *)u.u_ap;
89*7497Sroot 	register struct file *fp;
90*7497Sroot 
91*7497Sroot 	fp = getf(uap->i);
92*7497Sroot 	if (fp == 0)
93*7497Sroot 		return;
94*7497Sroot 	u.u_ofile[uap->i] = 0;
95*7497Sroot 	closef(fp, 0);
96*7497Sroot 	/* WHAT IF u.u_error ? */
97*7497Sroot }
98*7497Sroot 
99*7497Sroot dtype()
100*7497Sroot {
101*7497Sroot 	register struct a {
102*7497Sroot 		int	d;
103*7497Sroot 		struct	dtype *dtypeb;
104*7497Sroot 	} *uap = (struct a *)u.u_ap;
105*7497Sroot 	register struct file *fp;
106*7497Sroot 	struct dtype adtype;
107*7497Sroot 
108*7497Sroot 	fp = getf(uap->d);
109*7497Sroot 	if (fp == 0)
110*7497Sroot 		return;
111*7497Sroot 	adtype.dt_type = 0;		/* XXX */
112*7497Sroot 	adtype.dt_protocol = 0;		/* XXX */
113*7497Sroot 	if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
114*7497Sroot 	    sizeof (struct dtype)) < 0) {
115*7497Sroot 		u.u_error = EFAULT;
116*7497Sroot 		return;
117*7497Sroot 	}
118*7497Sroot }
119*7497Sroot 
120*7497Sroot dwrap()
121*7497Sroot {
122*7497Sroot 	register struct a {
123*7497Sroot 		int	d;
124*7497Sroot 		struct	dtype *dtypeb;
125*7497Sroot 	} *uap = (struct a *)u.u_ap;
126*7497Sroot 	register struct file *fp;
127*7497Sroot 	struct dtype adtype;
128*7497Sroot 
129*7497Sroot 	fp = getf(uap->d);
130*7497Sroot 	if (fp == 0)
131*7497Sroot 		return;
132*7497Sroot 	if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
133*7497Sroot 	    sizeof (struct dtype)) < 0) {
134*7497Sroot 		u.u_error = EFAULT;
135*7497Sroot 		return;
136*7497Sroot 	}
137*7497Sroot 	/* DO WRAP */
138*7497Sroot }
139*7497Sroot 
140*7497Sroot dselect()
141*7497Sroot {
142*7497Sroot 
143*7497Sroot }
144*7497Sroot 
145*7497Sroot dnblock()
146*7497Sroot {
147*7497Sroot 	register struct a {
148*7497Sroot 		int	d;
149*7497Sroot 		int	how;
150*7497Sroot 	} *uap = (struct a *)u.u_ap;
151*7497Sroot 
152*7497Sroot 	/* XXX */
153*7497Sroot }
154*7497Sroot 
155*7497Sroot dsignal()
156*7497Sroot {
157*7497Sroot 	register struct a {
158*7497Sroot 		int	d;
159*7497Sroot 		int	how;
160*7497Sroot 	} *uap = (struct a *)u.u_ap;
161*7497Sroot 
162*7497Sroot 	/* XXX */
163*7497Sroot }
164*7497Sroot 
1657422Sroot int	nselcoll;
1667422Sroot /*
1677422Sroot  * Select system call.
1687422Sroot  */
169*7497Sroot oselect()
1707422Sroot {
1717422Sroot 	register struct uap  {
1727422Sroot 		int	nfd;
1737422Sroot 		fd_set	*rp, *wp;
1747422Sroot 		int	timo;
1757422Sroot 	} *ap = (struct uap *)u.u_ap;
1767422Sroot 	fd_set rd, wr;
1777422Sroot 	int nfds = 0, readable = 0, writeable = 0;
1787422Sroot 	time_t t = time;
1797422Sroot 	int s, tsel, ncoll, rem;
1807422Sroot 
1817422Sroot 	if (ap->nfd > NOFILE)
1827422Sroot 		ap->nfd = NOFILE;
1837422Sroot 	if (ap->nfd < 0) {
1847422Sroot 		u.u_error = EBADF;
1857422Sroot 		return;
1867422Sroot 	}
1877422Sroot 	if (ap->rp && copyin((caddr_t)ap->rp,(caddr_t)&rd,sizeof(fd_set)))
1887422Sroot 		return;
1897422Sroot 	if (ap->wp && copyin((caddr_t)ap->wp,(caddr_t)&wr,sizeof(fd_set)))
1907422Sroot 		return;
1917422Sroot retry:
1927422Sroot 	ncoll = nselcoll;
1937422Sroot 	u.u_procp->p_flag |= SSEL;
1947422Sroot 	if (ap->rp)
1957422Sroot 		readable = selscan(ap->nfd, rd, &nfds, FREAD);
1967422Sroot 	if (ap->wp)
1977422Sroot 		writeable = selscan(ap->nfd, wr, &nfds, FWRITE);
1987422Sroot 	if (u.u_error)
1997422Sroot 		goto done;
2007422Sroot 	if (readable || writeable)
2017422Sroot 		goto done;
2027422Sroot 	rem = (ap->timo+999)/1000 - (time - t);
2037422Sroot 	if (ap->timo == 0 || rem <= 0)
2047422Sroot 		goto done;
2057422Sroot 	s = spl6();
2067422Sroot 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
2077422Sroot 		u.u_procp->p_flag &= ~SSEL;
2087422Sroot 		splx(s);
2097422Sroot 		goto retry;
2107422Sroot 	}
2117422Sroot 	u.u_procp->p_flag &= ~SSEL;
2127422Sroot 	tsel = tsleep((caddr_t)&selwait, PZERO+1, rem);
2137422Sroot 	splx(s);
2147422Sroot 	switch (tsel) {
2157422Sroot 
2167422Sroot 	case TS_OK:
2177422Sroot 		goto retry;
2187422Sroot 
2197422Sroot 	case TS_SIG:
2207422Sroot 		u.u_error = EINTR;
2217422Sroot 		return;
2227422Sroot 
2237422Sroot 	case TS_TIME:
2247422Sroot 		break;
2257422Sroot 	}
2267422Sroot done:
2277422Sroot 	rd.fds_bits[0] = readable;
2287422Sroot 	wr.fds_bits[0] = writeable;
2297422Sroot 	s = sizeof (fd_set);
2307422Sroot 	if (s * NBBY > ap->nfd)
2317422Sroot 		s = (ap->nfd + NBBY - 1) / NBBY;
2327422Sroot 	u.u_r.r_val1 = nfds;
2337422Sroot 	if (ap->rp)
2347422Sroot 		(void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set));
2357422Sroot 	if (ap->wp)
2367422Sroot 		(void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set));
2377422Sroot }
2387422Sroot 
2397422Sroot selscan(nfd, fds, nfdp, flag)
2407422Sroot 	int nfd;
2417422Sroot 	fd_set fds;
2427422Sroot 	int *nfdp, flag;
2437422Sroot {
2447422Sroot 	struct file *fp;
2457422Sroot 	struct inode *ip;
2467422Sroot 	register int bits;
2477422Sroot 	int i, able, res = 0;
2487422Sroot 
2497422Sroot 	bits = fds.fds_bits[0];
2507422Sroot 	while (i = ffs(bits)) {
2517422Sroot 		if (i > nfd)
2527422Sroot 			break;
2537422Sroot 		bits &= ~(1<<(i-1));
2547422Sroot 		fp = u.u_ofile[i-1];
2557422Sroot 		if (fp == NULL) {
2567422Sroot 			u.u_error = EBADF;
2577422Sroot 			return (0);
2587422Sroot 		}
259*7497Sroot 		if (fp->f_type == DTYPE_SOCKET)
2607422Sroot 			able = soselect(fp->f_socket, flag);
2617422Sroot 		else {
2627422Sroot 			ip = fp->f_inode;
2637422Sroot 			switch (ip->i_mode & IFMT) {
2647422Sroot 
2657422Sroot 			case IFCHR:
2667422Sroot 				able =
2677422Sroot 				    (*cdevsw[major(ip->i_rdev)].d_select)
2687422Sroot 					(ip->i_rdev, flag);
2697422Sroot 				break;
2707422Sroot 
2717422Sroot 			case IFBLK:
2727422Sroot 			case IFREG:
2737422Sroot 			case IFDIR:
2747422Sroot 				able = 1;
2757422Sroot 				break;
2767422Sroot 			}
277*7497Sroot 
2787422Sroot 		}
2797422Sroot 		if (able) {
2807422Sroot 			res |= (1<<(i-1));
2817422Sroot 			(*nfdp)++;
2827422Sroot 		}
2837422Sroot 	}
2847422Sroot 	return (res);
2857422Sroot }
2867422Sroot 
2877422Sroot /*ARGSUSED*/
2887422Sroot seltrue(dev, flag)
2897422Sroot 	dev_t dev;
2907422Sroot 	int flag;
2917422Sroot {
2927422Sroot 
2937422Sroot 	return (1);
2947422Sroot }
2957422Sroot 
2967422Sroot selwakeup(p, coll)
2977422Sroot 	register struct proc *p;
2987422Sroot 	int coll;
2997422Sroot {
3007422Sroot 	int s;
3017422Sroot 
3027422Sroot 	if (coll) {
3037422Sroot 		nselcoll++;
3047422Sroot 		wakeup((caddr_t)&selwait);
3057422Sroot 	}
3067422Sroot 	if (p) {
3077422Sroot 		if (p->p_wchan == (caddr_t)&selwait)
3087422Sroot 			setrun(p);
3097422Sroot 		else {
3107422Sroot 			s = spl6();
3117422Sroot 			if (p->p_flag & SSEL)
3127422Sroot 				p->p_flag &= ~SSEL;
3137422Sroot 			splx(s);
3147422Sroot 		}
3157422Sroot 	}
3167422Sroot }
3177422Sroot 
318*7497Sroot 
3197422Sroot /*
320*7497Sroot  * Allocate a user file descriptor.
3217422Sroot  */
322*7497Sroot ufalloc()
3237422Sroot {
324*7497Sroot 	register i;
325*7497Sroot 
326*7497Sroot 	for (i=0; i<NOFILE; i++)
327*7497Sroot 		if (u.u_ofile[i] == NULL) {
328*7497Sroot 			u.u_r.r_val1 = i;
329*7497Sroot 			u.u_pofile[i] = 0;
330*7497Sroot 			return (i);
331*7497Sroot 		}
332*7497Sroot 	u.u_error = EMFILE;
333*7497Sroot 	return (-1);
334*7497Sroot }
335*7497Sroot 
336*7497Sroot struct	file *lastf;
337*7497Sroot /*
338*7497Sroot  * Allocate a user file descriptor
339*7497Sroot  * and a file structure.
340*7497Sroot  * Initialize the descriptor
341*7497Sroot  * to point at the file structure.
342*7497Sroot  */
343*7497Sroot struct file *
344*7497Sroot falloc()
345*7497Sroot {
3467422Sroot 	register struct file *fp;
347*7497Sroot 	register i;
3487422Sroot 
349*7497Sroot 	i = ufalloc();
350*7497Sroot 	if (i < 0)
351*7497Sroot 		return (NULL);
352*7497Sroot 	if (lastf == 0)
353*7497Sroot 		lastf = file;
354*7497Sroot 	for (fp = lastf; fp < fileNFILE; fp++)
355*7497Sroot 		if (fp->f_count == 0)
356*7497Sroot 			goto slot;
357*7497Sroot 	for (fp = file; fp < lastf; fp++)
358*7497Sroot 		if (fp->f_count == 0)
359*7497Sroot 			goto slot;
360*7497Sroot 	tablefull("file");
361*7497Sroot 	u.u_error = ENFILE;
362*7497Sroot 	return (NULL);
363*7497Sroot slot:
364*7497Sroot 	u.u_ofile[i] = fp;
365*7497Sroot 	fp->f_count++;
366*7497Sroot 	fp->f_offset = 0;
367*7497Sroot 	fp->f_inode = 0;
368*7497Sroot 	lastf = fp + 1;
369*7497Sroot 	return (fp);
370*7497Sroot }
371*7497Sroot /*
372*7497Sroot  * Convert a user supplied file descriptor into a pointer
373*7497Sroot  * to a file structure.  Only task is to check range of the descriptor.
374*7497Sroot  * Critical paths should use the GETF macro, defined in inline.h.
375*7497Sroot  */
376*7497Sroot struct file *
377*7497Sroot getf(f)
378*7497Sroot 	register int f;
379*7497Sroot {
380*7497Sroot 	register struct file *fp;
381*7497Sroot 
382*7497Sroot 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
383*7497Sroot 		u.u_error = EBADF;
384*7497Sroot 		return (NULL);
385*7497Sroot 	}
386*7497Sroot 	return (fp);
387*7497Sroot }
388*7497Sroot 
389*7497Sroot /*
390*7497Sroot  * Internal form of close.
391*7497Sroot  * Decrement reference count on
392*7497Sroot  * file structure.
393*7497Sroot  * Also make sure the pipe protocol
394*7497Sroot  * does not constipate.
395*7497Sroot  *
396*7497Sroot  * Decrement reference count on the inode following
397*7497Sroot  * removal to the referencing file structure.
398*7497Sroot  * Call device handler on last close.
399*7497Sroot  * Nouser indicates that the user isn't available to present
400*7497Sroot  * errors to.
401*7497Sroot  */
402*7497Sroot closef(fp, nouser)
403*7497Sroot 	register struct file *fp;
404*7497Sroot {
405*7497Sroot 	register struct inode *ip;
406*7497Sroot 	register struct mount *mp;
407*7497Sroot 	int flag, mode;
408*7497Sroot 	dev_t dev;
409*7497Sroot 	register int (*cfunc)();
410*7497Sroot 
4117422Sroot 	if (fp == NULL)
4127422Sroot 		return;
413*7497Sroot 	if (fp->f_count > 1) {
414*7497Sroot 		fp->f_count--;
4157422Sroot 		return;
4167422Sroot 	}
417*7497Sroot 	if (fp->f_type == DTYPE_SOCKET) {
418*7497Sroot 		u.u_error = 0;			/* XXX */
419*7497Sroot 		soclose(fp->f_socket, nouser);
420*7497Sroot 		if (nouser == 0 && u.u_error)
421*7497Sroot 			return;
422*7497Sroot 		fp->f_socket = 0;
423*7497Sroot 		fp->f_count = 0;
424*7497Sroot 		return;
425*7497Sroot 	}
426*7497Sroot 	flag = fp->f_flag;
427*7497Sroot 	ip = fp->f_inode;
428*7497Sroot 	dev = (dev_t)ip->i_rdev;
429*7497Sroot 	mode = ip->i_mode & IFMT;
430*7497Sroot 	ilock(ip);
431*7497Sroot 	iput(ip);
432*7497Sroot 	fp->f_count = 0;
433*7497Sroot 
434*7497Sroot 	switch (mode) {
435*7497Sroot 
436*7497Sroot 	case IFCHR:
437*7497Sroot 		cfunc = cdevsw[major(dev)].d_close;
438*7497Sroot #ifdef EFS
439*7497Sroot 		/*
440*7497Sroot 		 * Every close() must call the driver if the
441*7497Sroot 		 * extended file system is being used -- not
442*7497Sroot 		 * just the last close.  Pass along the file
443*7497Sroot 		 * pointer for reference later.
444*7497Sroot 		 */
445*7497Sroot 		if (major(dev) == efs_major) {
446*7497Sroot 			(*cfunc)(dev, flag, fp, nouser);
447*7497Sroot 			return;
448*7497Sroot 		}
449*7497Sroot #endif
450*7497Sroot 		break;
451*7497Sroot 
452*7497Sroot 	case IFBLK:
453*7497Sroot 		/*
454*7497Sroot 		 * We don't want to really close the device if it is mounted
455*7497Sroot 		 */
456*7497Sroot 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
457*7497Sroot 			if (mp->m_bufp != NULL && mp->m_dev == dev)
458*7497Sroot 				return;
459*7497Sroot 		cfunc = bdevsw[major(dev)].d_close;
460*7497Sroot 		break;
461*7497Sroot 
462*7497Sroot 	default:
463*7497Sroot 		return;
464*7497Sroot 	}
465*7497Sroot 	for (fp = file; fp < fileNFILE; fp++) {
466*7497Sroot 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
467*7497Sroot 			continue;
468*7497Sroot 		if (fp->f_count && (ip = fp->f_inode) &&
469*7497Sroot 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
470*7497Sroot 			return;
471*7497Sroot 	}
472*7497Sroot 	if (mode == IFBLK) {
473*7497Sroot 		/*
474*7497Sroot 		 * On last close of a block device (that isn't mounted)
475*7497Sroot 		 * we must invalidate any in core blocks
476*7497Sroot 		 */
477*7497Sroot 		bflush(dev);
478*7497Sroot 		binval(dev);
479*7497Sroot 	}
480*7497Sroot 	(*cfunc)(dev, flag, fp);
4817422Sroot }
482*7497Sroot 
483*7497Sroot #ifdef CAD
484*7497Sroot /*
485*7497Sroot  * chfile -- change all references to the inode named by
486*7497Sroot  *	     device/inum to the file referred to by fd.
487*7497Sroot  * Used by init to remove all references to the device.
488*7497Sroot  */
489*7497Sroot chfile()
490*7497Sroot {
491*7497Sroot 	register struct file *fp;
492*7497Sroot 	register struct inode *from;
493*7497Sroot 	register struct inode *to;
494*7497Sroot 	off_t offset;
495*7497Sroot 	dev_t dev;
496*7497Sroot 	int rw;
497*7497Sroot 	struct a {
498*7497Sroot 		int	device;		/* actually dev_t */
499*7497Sroot 		int	inum;		/* actually ino_t */
500*7497Sroot 		int	fd;
501*7497Sroot 	} *uap;
502*7497Sroot 
503*7497Sroot 	if (!suser()) {
504*7497Sroot 		u.u_error = EPERM;
505*7497Sroot 		return;
506*7497Sroot 	}
507*7497Sroot 	uap = (struct a *) u.u_ap;
508*7497Sroot 	fp = getf(uap->fd);
509*7497Sroot 	if (fp == NULL) {
510*7497Sroot 		u.u_error = EBADF;
511*7497Sroot 		return;
512*7497Sroot 	}
513*7497Sroot 	if (fp->f_type == DTYPE_SOCKET) {
514*7497Sroot 		u.u_error = EINVAL;
515*7497Sroot 		return;
516*7497Sroot 	}
517*7497Sroot 	for (from = &inode[0]; from < &inode[ninode]; from++)
518*7497Sroot 		if (from->i_number == (ino_t)uap->inum
519*7497Sroot 		   && from->i_dev == (dev_t)uap->device)
520*7497Sroot 			break;
521*7497Sroot 	if (from >= &inode[ninode]) {
522*7497Sroot 		u.u_error = ENXIO;
523*7497Sroot 		return;
524*7497Sroot 	}
525*7497Sroot 	offset = fp->f_offset;
526*7497Sroot 	to = fp->f_inode;
527*7497Sroot 	from->i_count++;
528*7497Sroot 	for (fp = &file[0]; fp < &file[nfile]; fp++) {
529*7497Sroot 		if (fp->f_count > 0 && fp->f_inode == from) {
530*7497Sroot 			fp->f_inode = to;
531*7497Sroot 			to->i_count++;
532*7497Sroot 			fp->f_offset = offset;
533*7497Sroot 			rw |= fp->f_flag & FWRITE;
534*7497Sroot 			iput(from);
535*7497Sroot 		}
536*7497Sroot 	}
537*7497Sroot 	/*
538*7497Sroot 	 * This inode is no longer referenced.
539*7497Sroot 	 * Switch out to the appropriate close
540*7497Sroot 	 * routine, if required
541*7497Sroot 	 */
542*7497Sroot 	dev = (dev_t)from->i_un.i_rdev;
543*7497Sroot 	switch(from->i_mode & IFMT) {
544*7497Sroot 
545*7497Sroot 	case IFCHR:
546*7497Sroot 		(*cdevsw[major(dev)].d_close)(dev, rw);
547*7497Sroot 		break;
548*7497Sroot 
549*7497Sroot 	case IFBLK:
550*7497Sroot 		(*bdevsw[major(dev)].d_close)(dev, rw);
551*7497Sroot 		break;
552*7497Sroot 
553*7497Sroot 	default:
554*7497Sroot 		break;
555*7497Sroot 	}
556*7497Sroot 	iput(from);
557*7497Sroot }
558*7497Sroot #endif
559