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