xref: /csrg-svn/sys/kern/kern_descrip.c (revision 8622)
1 /*	kern_descrip.c	5.13	82/10/17	*/
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 	if (uap->nd >= NOFILE) {
185 		u.u_error = EINVAL;
186 		return;
187 	}
188 
189 #define	getbits(name, x) \
190 	if (uap->name) { \
191 		if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
192 		    sizeof (ibits[x]))) { \
193 			u.u_error = EFAULT; \
194 			return; \
195 		} \
196 	} else \
197 		ibits[x] = 0;
198 	getbits(in, 0);
199 	getbits(ou, 1);
200 	getbits(ex, 2);
201 #undef	getbits
202 
203 	if (uap->tv) {
204 		if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) {
205 			u.u_error = EFAULT;
206 			return;
207 		}
208 		if (itimerfix(&atv)) {
209 			u.u_error = EINVAL;
210 			return;
211 		}
212 		s = spl7(); timevaladd(&atv, &time); splx(s);
213 	}
214 retry:
215 	ncoll = nselcoll;
216 	u.u_procp->p_flag |= SSEL;
217 	u.u_r.r_val1 = selscan(ibits, obits);
218 	if (u.u_error)
219 		return;
220 	if (u.u_r.r_val1)
221 		goto done;
222 	s = spl6();
223 	if (uap->tv && timercmp(&time, &atv, >=)) {
224 		splx(s);
225 		goto done;
226 	}
227 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
228 		u.u_procp->p_flag &= ~SSEL;
229 		splx(s);
230 		goto retry;
231 	}
232 	u.u_procp->p_flag &= ~SSEL;
233 	if (uap->tv) {
234 		lqsave = u.u_qsave;
235 		if (setjmp(&u.u_qsave)) {
236 			untimeout(unselect, (caddr_t)u.u_procp);
237 			u.u_error = EINTR;
238 			splx(s);
239 			return;
240 		}
241 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
242 	}
243 	sleep((caddr_t)&selwait, PZERO+1);
244 	if (uap->tv) {
245 		u.u_qsave = lqsave;
246 		untimeout(unselect, (caddr_t)u.u_procp);
247 	}
248 	splx(s);
249 	goto retry;
250 done:
251 #define	putbits(name, x) \
252 	if (uap->name) { \
253 		if (copyout((caddr_t)obits[x], (caddr_t)uap->name, \
254 		    sizeof (obits[x]))) { \
255 			u.u_error = EFAULT; \
256 			return; \
257 		} \
258 	}
259 	putbits(in, 0);
260 	putbits(ou, 1);
261 	putbits(ex, 2);
262 #undef putbits
263 }
264 
265 unselect(p)
266 	register struct proc *p;
267 {
268 	register int s = spl6();
269 
270 	switch (p->p_stat) {
271 
272 	case SSLEEP:
273 		setrun(p);
274 		break;
275 
276 	case SSTOP:
277 		unsleep(p);
278 		break;
279 	}
280 	splx(s);
281 }
282 
283 selscan(ibits, obits)
284 	int *ibits, *obits;
285 {
286 	register int which, bits, i;
287 	int flag;
288 	struct file *fp;
289 	int able;
290 	struct inode *ip;
291 	int n = 0;
292 
293 	for (which = 0; which < 3; which++) {
294 		bits = ibits[which];
295 		obits[which] = 0;
296 		switch (which) {
297 
298 		case 0:
299 			flag = FREAD; break;
300 
301 		case 1:
302 			flag = FWRITE; break;
303 
304 		case 2:
305 			flag = 0; break;
306 		}
307 		while (i = ffs(bits)) {
308 			bits &= ~(1<<(i-1));
309 			fp = u.u_ofile[i-1];
310 			if (fp == NULL) {
311 				u.u_error = EBADF;
312 				break;
313 			}
314 			if (fp->f_type == DTYPE_SOCKET)
315 				able = soselect(fp->f_socket, flag);
316 			else {
317 				ip = fp->f_inode;
318 				switch (ip->i_mode & IFMT) {
319 
320 				case IFCHR:
321 					able =
322 					    (*cdevsw[major(ip->i_rdev)].d_select)
323 						(ip->i_rdev, flag);
324 					break;
325 
326 				case IFBLK:
327 				case IFREG:
328 				case IFDIR:
329 					able = 1;
330 					break;
331 				}
332 
333 			}
334 			if (able) {
335 				obits[which] |= (1<<(i-1));
336 				n++;
337 			}
338 		}
339 	}
340 	return (n);
341 }
342 
343 /*ARGSUSED*/
344 seltrue(dev, flag)
345 	dev_t dev;
346 	int flag;
347 {
348 
349 	return (1);
350 }
351 
352 selwakeup(p, coll)
353 	register struct proc *p;
354 	int coll;
355 {
356 	int s;
357 
358 	if (coll) {
359 		nselcoll++;
360 		wakeup((caddr_t)&selwait);
361 	}
362 	if (p) {
363 		if (p->p_wchan == (caddr_t)&selwait)
364 			setrun(p);
365 		else {
366 			s = spl6();
367 			if (p->p_flag & SSEL)
368 				p->p_flag &= ~SSEL;
369 			splx(s);
370 		}
371 	}
372 }
373 
374 revoke()
375 {
376 
377 	/* XXX */
378 }
379 
380 /*
381  * Allocate a user file descriptor.
382  */
383 ufalloc()
384 {
385 	register i;
386 
387 	for (i=0; i<NOFILE; i++)
388 		if (u.u_ofile[i] == NULL) {
389 			u.u_r.r_val1 = i;
390 			u.u_pofile[i] = 0;
391 			return (i);
392 		}
393 	u.u_error = EMFILE;
394 	return (-1);
395 }
396 
397 struct	file *lastf;
398 /*
399  * Allocate a user file descriptor
400  * and a file structure.
401  * Initialize the descriptor
402  * to point at the file structure.
403  */
404 struct file *
405 falloc()
406 {
407 	register struct file *fp;
408 	register i;
409 
410 	i = ufalloc();
411 	if (i < 0)
412 		return (NULL);
413 	if (lastf == 0)
414 		lastf = file;
415 	for (fp = lastf; fp < fileNFILE; fp++)
416 		if (fp->f_count == 0)
417 			goto slot;
418 	for (fp = file; fp < lastf; fp++)
419 		if (fp->f_count == 0)
420 			goto slot;
421 	tablefull("file");
422 	u.u_error = ENFILE;
423 	return (NULL);
424 slot:
425 	u.u_ofile[i] = fp;
426 	fp->f_count++;
427 	fp->f_offset = 0;
428 	fp->f_inode = 0;
429 	lastf = fp + 1;
430 	return (fp);
431 }
432 /*
433  * Convert a user supplied file descriptor into a pointer
434  * to a file structure.  Only task is to check range of the descriptor.
435  * Critical paths should use the GETF macro, defined in inline.h.
436  */
437 struct file *
438 getf(f)
439 	register int f;
440 {
441 	register struct file *fp;
442 
443 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
444 		u.u_error = EBADF;
445 		return (NULL);
446 	}
447 	return (fp);
448 }
449 
450 /*
451  * Internal form of close.
452  * Decrement reference count on
453  * file structure.
454  * Also make sure the pipe protocol
455  * does not constipate.
456  *
457  * Decrement reference count on the inode following
458  * removal to the referencing file structure.
459  * Call device handler on last close.
460  * Nouser indicates that the user isn't available to present
461  * errors to.
462  *
463  * Handling locking at this level is RIDICULOUS.
464  */
465 closef(fp, nouser, flags)
466 	register struct file *fp;
467 	int nouser, flags;
468 {
469 	register struct inode *ip;
470 	register struct mount *mp;
471 	int flag, mode;
472 	dev_t dev;
473 	register int (*cfunc)();
474 
475 	if (fp == NULL)
476 		return;
477 	if (fp->f_count > 1) {
478 		fp->f_count--;
479 		return;
480 	}
481 	if (fp->f_type == DTYPE_SOCKET) {
482 		u.u_error = 0;			/* XXX */
483 		soclose(fp->f_socket, nouser);
484 		if (nouser == 0 && u.u_error)
485 			return;
486 		fp->f_socket = 0;
487 		fp->f_count = 0;
488 		return;
489 	}
490 	flag = fp->f_flag;
491 	ip = fp->f_inode;
492 	dev = (dev_t)ip->i_rdev;
493 	mode = ip->i_mode & IFMT;
494 	flags &= RDLOCK|WRLOCK;			/* conservative */
495 	if (flags)
496 		funlocki(ip, flags);
497 	ilock(ip);
498 	iput(ip);
499 	fp->f_count = 0;
500 
501 	switch (mode) {
502 
503 	case IFCHR:
504 		cfunc = cdevsw[major(dev)].d_close;
505 		break;
506 
507 	case IFBLK:
508 		/*
509 		 * We don't want to really close the device if it is mounted
510 		 */
511 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
512 			if (mp->m_bufp != NULL && mp->m_dev == dev)
513 				return;
514 		cfunc = bdevsw[major(dev)].d_close;
515 		break;
516 
517 	default:
518 		return;
519 	}
520 	for (fp = file; fp < fileNFILE; fp++) {
521 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
522 			continue;
523 		if (fp->f_count && (ip = fp->f_inode) &&
524 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
525 			return;
526 	}
527 	if (mode == IFBLK) {
528 		/*
529 		 * On last close of a block device (that isn't mounted)
530 		 * we must invalidate any in core blocks
531 		 */
532 		bflush(dev);
533 		binval(dev);
534 	}
535 	(*cfunc)(dev, flag, fp);
536 }
537 
538 opause()
539 {
540 
541 	for (;;)
542 		sleep((caddr_t)&u, PSLEP);
543 }
544