xref: /csrg-svn/sys/kern/kern_descrip.c (revision 8836)
1 /*	kern_descrip.c	5.16	82/10/23	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/kernel.h"
8 #include "../h/inode.h"
9 #include "../h/proc.h"
10 #include "../h/conf.h"
11 #include "../h/file.h"
12 #include "../h/socket.h"
13 #include "../h/socketvar.h"
14 #include "../h/mount.h"
15 
16 #include "../h/descrip.h"
17 
18 /*
19  * Descriptor management.
20  */
21 
22 /*
23  * TODO:
24  *	getf should be renamed
25  *	ufalloc side effects are gross
26  */
27 
28 /*
29  * System calls on descriptors.
30  */
31 getdtablesize()
32 {
33 
34 	u.u_r.r_val1 = NOFILE;
35 }
36 
37 getdprop()
38 {
39 	register struct a {
40 		int	d;
41 		struct	dtype *dtypeb;
42 	} *uap = (struct a *)u.u_ap;
43 	register struct file *fp;
44 	struct dtype adtype;
45 
46 	fp = getf(uap->d);
47 	if (fp == 0)
48 		return;
49 	adtype.dt_type = 0;		/* XXX */
50 	adtype.dt_protocol = 0;		/* XXX */
51 	if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
52 	    sizeof (struct dtype)) < 0) {
53 		u.u_error = EFAULT;
54 		return;
55 	}
56 }
57 
58 getdopt()
59 {
60 
61 }
62 
63 setdopt()
64 {
65 
66 }
67 
68 dup()
69 {
70 	register struct a {
71 		int	i;
72 	} *uap = (struct a *) u.u_ap;
73 	struct file *fp;
74 	int j;
75 
76 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
77 
78 	fp = getf(uap->i);
79 	if (fp == 0)
80 		return;
81 	j = ufalloc();
82 	if (j < 0)
83 		return;
84 	dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK));
85 }
86 
87 dup2()
88 {
89 	register struct a {
90 		int	i, j;
91 	} *uap = (struct a *) u.u_ap;
92 	register struct file *fp;
93 
94 	fp = getf(uap->i);
95 	if (fp == 0)
96 		return;
97 	if (uap->j < 0 || uap->j >= NOFILE) {
98 		u.u_error = EBADF;
99 		return;
100 	}
101 	u.u_r.r_val1 = uap->j;
102 	if (uap->i == uap->j)
103 		return;
104 	if (u.u_ofile[uap->j]) {
105 		closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]);
106 		if (u.u_error)
107 			return;
108 		/* u.u_ofile[uap->j] = 0; */
109 		/* u.u_pofile[uap->j] = 0; */
110 	}
111 	dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK));
112 }
113 
114 dupit(fd, fp, lockflags)
115 	int fd;
116 	register struct file *fp;
117 	register int lockflags;
118 {
119 
120 	u.u_ofile[fd] = fp;
121 	u.u_pofile[fd] = lockflags;
122 	fp->f_count++;
123 	if (lockflags&RDLOCK)
124 		fp->f_inode->i_rdlockc++;
125 	if (lockflags&WRLOCK)
126 		fp->f_inode->i_wrlockc++;
127 }
128 
129 close()
130 {
131 	register struct a {
132 		int	i;
133 	} *uap = (struct a *)u.u_ap;
134 	register struct file *fp;
135 
136 	fp = getf(uap->i);
137 	if (fp == 0)
138 		return;
139 	closef(fp, 0, u.u_pofile[uap->i]);
140 	/* WHAT IF u.u_error ? */
141 	u.u_ofile[uap->i] = NULL;
142 	u.u_pofile[uap->i] = 0;
143 }
144 
145 wrap()
146 {
147 	register struct a {
148 		int	d;
149 		struct	dtype *dtypeb;
150 	} *uap = (struct a *)u.u_ap;
151 	register struct file *fp;
152 	struct dtype adtype;
153 
154 	fp = getf(uap->d);
155 	if (fp == 0)
156 		return;
157 	if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
158 	    sizeof (struct dtype)) < 0) {
159 		u.u_error = EFAULT;
160 		return;
161 	}
162 	/* DO WRAP */
163 }
164 
165 int	unselect();
166 int	nselcoll;
167 /*
168  * Select system call.
169  */
170 select()
171 {
172 	register struct uap  {
173 		int	nd;
174 		long	*in;
175 		long	*ou;
176 		long	*ex;
177 		struct	timeval *tv;
178 	} *uap = (struct uap *)u.u_ap;
179 	int ibits[3], obits[3];
180 	struct timeval atv;
181 	int s, ncoll;
182 	label_t lqsave;
183 
184 	obits[0] = obits[1] = obits[2] = 0;
185 	if (uap->nd > NOFILE)
186 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
187 
188 #define	getbits(name, x) \
189 	if (uap->name) { \
190 		if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
191 		    sizeof (ibits[x]))) { \
192 			u.u_error = EFAULT; \
193 			goto done; \
194 		} \
195 	} else \
196 		ibits[x] = 0;
197 	getbits(in, 0);
198 	getbits(ou, 1);
199 	getbits(ex, 2);
200 #undef	getbits
201 
202 	if (uap->tv) {
203 		if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) {
204 			u.u_error = EFAULT;
205 			goto done;
206 		}
207 		if (itimerfix(&atv)) {
208 			u.u_error = EINVAL;
209 			goto done;
210 		}
211 		s = spl7(); timevaladd(&atv, &time); splx(s);
212 	}
213 retry:
214 	ncoll = nselcoll;
215 	u.u_procp->p_flag |= SSEL;
216 	u.u_r.r_val1 = selscan(ibits, obits);
217 	if (u.u_error || u.u_r.r_val1)
218 		goto done;
219 	s = spl6();
220 	if (uap->tv && timercmp(&time, &atv, >=)) {
221 		splx(s);
222 		goto done;
223 	}
224 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
225 		u.u_procp->p_flag &= ~SSEL;
226 		splx(s);
227 		goto retry;
228 	}
229 	u.u_procp->p_flag &= ~SSEL;
230 	if (uap->tv) {
231 		lqsave = u.u_qsave;
232 		if (setjmp(&u.u_qsave)) {
233 			untimeout(unselect, (caddr_t)u.u_procp);
234 			u.u_error = EINTR;
235 			splx(s);
236 			goto done;
237 		}
238 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
239 	}
240 	sleep((caddr_t)&selwait, PZERO+1);
241 	if (uap->tv) {
242 		u.u_qsave = lqsave;
243 		untimeout(unselect, (caddr_t)u.u_procp);
244 	}
245 	splx(s);
246 	goto retry;
247 done:
248 #define	putbits(name, x) \
249 	if (uap->name) { \
250 		if (copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
251 		    sizeof (obits[x]))) \
252 			u.u_error = EFAULT; \
253 	}
254 	putbits(in, 0);
255 	putbits(ou, 1);
256 	putbits(ex, 2);
257 #undef putbits
258 }
259 
260 unselect(p)
261 	register struct proc *p;
262 {
263 	register int s = spl6();
264 
265 	switch (p->p_stat) {
266 
267 	case SSLEEP:
268 		setrun(p);
269 		break;
270 
271 	case SSTOP:
272 		unsleep(p);
273 		break;
274 	}
275 	splx(s);
276 }
277 
278 selscan(ibits, obits)
279 	int *ibits, *obits;
280 {
281 	register int which, bits, i;
282 	int flag;
283 	struct file *fp;
284 	int able;
285 	struct inode *ip;
286 	int n = 0;
287 
288 	for (which = 0; which < 3; which++) {
289 		bits = ibits[which];
290 		obits[which] = 0;
291 		switch (which) {
292 
293 		case 0:
294 			flag = FREAD; break;
295 
296 		case 1:
297 			flag = FWRITE; break;
298 
299 		case 2:
300 			flag = 0; break;
301 		}
302 		while (i = ffs(bits)) {
303 			bits &= ~(1<<(i-1));
304 			fp = u.u_ofile[i-1];
305 			if (fp == NULL) {
306 				u.u_error = EBADF;
307 				break;
308 			}
309 			if (fp->f_type == DTYPE_SOCKET)
310 				able = soselect(fp->f_socket, flag);
311 			else {
312 				ip = fp->f_inode;
313 				switch (ip->i_mode & IFMT) {
314 
315 				case IFCHR:
316 					able =
317 					    (*cdevsw[major(ip->i_rdev)].d_select)
318 						(ip->i_rdev, flag);
319 					break;
320 
321 				case IFBLK:
322 				case IFREG:
323 				case IFDIR:
324 					able = 1;
325 					break;
326 				}
327 
328 			}
329 			if (able) {
330 				obits[which] |= (1<<(i-1));
331 				n++;
332 			}
333 		}
334 	}
335 	return (n);
336 }
337 
338 /*ARGSUSED*/
339 seltrue(dev, flag)
340 	dev_t dev;
341 	int flag;
342 {
343 
344 	return (1);
345 }
346 
347 selwakeup(p, coll)
348 	register struct proc *p;
349 	int coll;
350 {
351 	int s;
352 
353 	if (coll) {
354 		nselcoll++;
355 		wakeup((caddr_t)&selwait);
356 	}
357 	if (p) {
358 		if (p->p_wchan == (caddr_t)&selwait)
359 			setrun(p);
360 		else {
361 			s = spl6();
362 			if (p->p_flag & SSEL)
363 				p->p_flag &= ~SSEL;
364 			splx(s);
365 		}
366 	}
367 }
368 
369 revoke()
370 {
371 
372 	/* XXX */
373 }
374 
375 /*
376  * Allocate a user file descriptor.
377  */
378 ufalloc()
379 {
380 	register i;
381 
382 	for (i=0; i<NOFILE; i++)
383 		if (u.u_ofile[i] == NULL) {
384 			u.u_r.r_val1 = i;
385 			u.u_pofile[i] = 0;
386 			return (i);
387 		}
388 	u.u_error = EMFILE;
389 	return (-1);
390 }
391 
392 struct	file *lastf;
393 /*
394  * Allocate a user file descriptor
395  * and a file structure.
396  * Initialize the descriptor
397  * to point at the file structure.
398  */
399 struct file *
400 falloc()
401 {
402 	register struct file *fp;
403 	register i;
404 
405 	i = ufalloc();
406 	if (i < 0)
407 		return (NULL);
408 	if (lastf == 0)
409 		lastf = file;
410 	for (fp = lastf; fp < fileNFILE; fp++)
411 		if (fp->f_count == 0)
412 			goto slot;
413 	for (fp = file; fp < lastf; fp++)
414 		if (fp->f_count == 0)
415 			goto slot;
416 	tablefull("file");
417 	u.u_error = ENFILE;
418 	return (NULL);
419 slot:
420 	u.u_ofile[i] = fp;
421 	fp->f_count++;
422 	fp->f_offset = 0;
423 	fp->f_inode = 0;
424 	lastf = fp + 1;
425 	return (fp);
426 }
427 /*
428  * Convert a user supplied file descriptor into a pointer
429  * to a file structure.  Only task is to check range of the descriptor.
430  * Critical paths should use the GETF macro, defined in inline.h.
431  */
432 struct file *
433 getf(f)
434 	register int f;
435 {
436 	register struct file *fp;
437 
438 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
439 		u.u_error = EBADF;
440 		return (NULL);
441 	}
442 	return (fp);
443 }
444 
445 /*
446  * Internal form of close.
447  * Decrement reference count on
448  * file structure.
449  * Also make sure the pipe protocol
450  * does not constipate.
451  *
452  * Decrement reference count on the inode following
453  * removal to the referencing file structure.
454  * Call device handler on last close.
455  * Nouser indicates that the user isn't available to present
456  * errors to.
457  *
458  * Handling locking at this level is RIDICULOUS.
459  */
460 closef(fp, nouser, flags)
461 	register struct file *fp;
462 	int nouser, flags;
463 {
464 	register struct inode *ip;
465 	register struct mount *mp;
466 	int flag, mode;
467 	dev_t dev;
468 	register int (*cfunc)();
469 
470 	if (fp == NULL)
471 		return;
472 	if (fp->f_count > 1) {
473 		fp->f_count--;
474 		return;
475 	}
476 	if (fp->f_type == DTYPE_SOCKET) {
477 		u.u_error = soclose(fp->f_socket, nouser);
478 		if (nouser == 0 && u.u_error)
479 			return;
480 		fp->f_socket = 0;
481 		fp->f_count = 0;
482 		return;
483 	}
484 	flag = fp->f_flag;
485 	ip = fp->f_inode;
486 	dev = (dev_t)ip->i_rdev;
487 	mode = ip->i_mode & IFMT;
488 	flags &= RDLOCK|WRLOCK;			/* conservative */
489 	if (flags)
490 		funlocki(ip, flags);
491 	ilock(ip);
492 	iput(ip);
493 	fp->f_count = 0;
494 
495 	switch (mode) {
496 
497 	case IFCHR:
498 		cfunc = cdevsw[major(dev)].d_close;
499 		break;
500 
501 	case IFBLK:
502 		/*
503 		 * We don't want to really close the device if it is mounted
504 		 */
505 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
506 			if (mp->m_bufp != NULL && mp->m_dev == dev)
507 				return;
508 		cfunc = bdevsw[major(dev)].d_close;
509 		break;
510 
511 	default:
512 		return;
513 	}
514 	for (fp = file; fp < fileNFILE; fp++) {
515 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
516 			continue;
517 		if (fp->f_count && (ip = fp->f_inode) &&
518 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
519 			return;
520 	}
521 	if (mode == IFBLK) {
522 		/*
523 		 * On last close of a block device (that isn't mounted)
524 		 * we must invalidate any in core blocks
525 		 */
526 		bflush(dev);
527 		binval(dev);
528 	}
529 	(*cfunc)(dev, flag, fp);
530 }
531 
532 opause()
533 {
534 
535 	for (;;)
536 		sleep((caddr_t)&u, PSLEP);
537 }
538