xref: /csrg-svn/sys/kern/kern_descrip.c (revision 10389)
1 /*	kern_descrip.c	5.23	83/01/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 	u.u_error = copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
52 	    sizeof (struct dtype));
53 	if (u.u_error)
54 		return;
55 }
56 
57 getdopt()
58 {
59 
60 }
61 
62 setdopt()
63 {
64 
65 }
66 
67 dup()
68 {
69 	register struct a {
70 		int	i;
71 	} *uap = (struct a *) u.u_ap;
72 	struct file *fp;
73 	int j;
74 
75 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
76 
77 	fp = getf(uap->i);
78 	if (fp == 0)
79 		return;
80 	j = ufalloc();
81 	if (j < 0)
82 		return;
83 	dupit(j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK));
84 }
85 
86 dup2()
87 {
88 	register struct a {
89 		int	i, j;
90 	} *uap = (struct a *) u.u_ap;
91 	register struct file *fp;
92 
93 	fp = getf(uap->i);
94 	if (fp == 0)
95 		return;
96 	if (uap->j < 0 || uap->j >= NOFILE) {
97 		u.u_error = EBADF;
98 		return;
99 	}
100 	u.u_r.r_val1 = uap->j;
101 	if (uap->i == uap->j)
102 		return;
103 	if (u.u_ofile[uap->j]) {
104 		if (u.u_pofile[uap->j] & UF_MAPPED)
105 			munmapfd(uap->j);
106 		closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]);
107 		if (u.u_error)
108 			return;
109 		/* u.u_ofile[uap->j] = 0; */
110 		/* u.u_pofile[uap->j] = 0; */
111 	}
112 	dupit(uap->j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK));
113 }
114 
115 dupit(fd, fp, lockflags)
116 	int fd;
117 	register struct file *fp;
118 	register int lockflags;
119 {
120 
121 	u.u_ofile[fd] = fp;
122 	u.u_pofile[fd] = lockflags;
123 	fp->f_count++;
124 	if (lockflags&UF_SHLOCK)
125 		fp->f_inode->i_shlockc++;
126 	if (lockflags&UF_EXLOCK)
127 		fp->f_inode->i_exlockc++;
128 }
129 
130 close()
131 {
132 	register struct a {
133 		int	i;
134 	} *uap = (struct a *)u.u_ap;
135 	register struct file *fp;
136 
137 	fp = getf(uap->i);
138 	if (fp == 0)
139 		return;
140 	if (u.u_pofile[uap->i] & UF_MAPPED)
141 		munmapfd(uap->i);
142 	closef(fp, 0, u.u_pofile[uap->i]);
143 	/* WHAT IF u.u_error ? */
144 	u.u_ofile[uap->i] = NULL;
145 	u.u_pofile[uap->i] = 0;
146 }
147 
148 wrap()
149 {
150 	register struct a {
151 		int	d;
152 		struct	dtype *dtypeb;
153 	} *uap = (struct a *)u.u_ap;
154 	register struct file *fp;
155 	struct dtype adtype;
156 
157 	fp = getf(uap->d);
158 	if (fp == 0)
159 		return;
160 	u.u_error = copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
161 	    sizeof (struct dtype));
162 	if (u.u_error)
163 		return;
164 	/* DO WRAP */
165 }
166 
167 int	unselect();
168 int	nselcoll;
169 /*
170  * Select system call.
171  */
172 select()
173 {
174 	register struct uap  {
175 		int	nd;
176 		long	*in;
177 		long	*ou;
178 		long	*ex;
179 		struct	timeval *tv;
180 	} *uap = (struct uap *)u.u_ap;
181 	int ibits[3], obits[3];
182 	struct timeval atv;
183 	int s, ncoll;
184 	label_t lqsave;
185 
186 	obits[0] = obits[1] = obits[2] = 0;
187 	if (uap->nd > NOFILE)
188 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
189 
190 #define	getbits(name, x) \
191 	if (uap->name) { \
192 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
193 		    sizeof (ibits[x])); \
194 		if (u.u_error) \
195 			goto done; \
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 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
205 			sizeof (atv));
206 		if (u.u_error)
207 			goto done;
208 		if (itimerfix(&atv)) {
209 			u.u_error = EINVAL;
210 			goto done;
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 || u.u_r.r_val1)
219 		goto done;
220 	s = spl6();
221 	if (uap->tv && timercmp(&time, &atv, >=)) {
222 		splx(s);
223 		goto done;
224 	}
225 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
226 		u.u_procp->p_flag &= ~SSEL;
227 		splx(s);
228 		goto retry;
229 	}
230 	u.u_procp->p_flag &= ~SSEL;
231 	if (uap->tv) {
232 		lqsave = u.u_qsave;
233 		if (setjmp(&u.u_qsave)) {
234 			untimeout(unselect, (caddr_t)u.u_procp);
235 			u.u_error = EINTR;
236 			splx(s);
237 			goto done;
238 		}
239 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
240 	}
241 	sleep((caddr_t)&selwait, PZERO+1);
242 	if (uap->tv) {
243 		u.u_qsave = lqsave;
244 		untimeout(unselect, (caddr_t)u.u_procp);
245 	}
246 	splx(s);
247 	goto retry;
248 done:
249 #define	putbits(name, x) \
250 	if (uap->name) { \
251 		int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
252 		    sizeof (obits[x])); \
253 		if (error) \
254 			u.u_error = error; \
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 
354 	if (coll) {
355 		nselcoll++;
356 		wakeup((caddr_t)&selwait);
357 	}
358 	if (p) {
359 		int s = spl6();
360 		if (p->p_wchan == (caddr_t)&selwait)
361 			setrun(p);
362 		else if (p->p_flag & SSEL)
363 			p->p_flag &= ~SSEL;
364 		splx(s);
365 	}
366 }
367 
368 revoke()
369 {
370 
371 	/* XXX */
372 }
373 
374 /*
375  * Allocate a user file descriptor.
376  */
377 ufalloc()
378 {
379 	register i;
380 
381 	for (i=0; i<NOFILE; i++)
382 		if (u.u_ofile[i] == NULL) {
383 			u.u_r.r_val1 = i;
384 			u.u_pofile[i] = 0;
385 			return (i);
386 		}
387 	u.u_error = EMFILE;
388 	return (-1);
389 }
390 
391 struct	file *lastf;
392 /*
393  * Allocate a user file descriptor
394  * and a file structure.
395  * Initialize the descriptor
396  * to point at the file structure.
397  */
398 struct file *
399 falloc()
400 {
401 	register struct file *fp;
402 	register i;
403 
404 	i = ufalloc();
405 	if (i < 0)
406 		return (NULL);
407 	if (lastf == 0)
408 		lastf = file;
409 	for (fp = lastf; fp < fileNFILE; fp++)
410 		if (fp->f_count == 0)
411 			goto slot;
412 	for (fp = file; fp < lastf; fp++)
413 		if (fp->f_count == 0)
414 			goto slot;
415 	tablefull("file");
416 	u.u_error = ENFILE;
417 	return (NULL);
418 slot:
419 	u.u_ofile[i] = fp;
420 	fp->f_count++;
421 	fp->f_offset = 0;
422 	fp->f_inode = 0;
423 	lastf = fp + 1;
424 	return (fp);
425 }
426 /*
427  * Convert a user supplied file descriptor into a pointer
428  * to a file structure.  Only task is to check range of the descriptor.
429  * Critical paths should use the GETF macro, defined in inline.h.
430  */
431 struct file *
432 getf(f)
433 	register int f;
434 {
435 	register struct file *fp;
436 
437 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
438 		u.u_error = EBADF;
439 		return (NULL);
440 	}
441 	return (fp);
442 }
443 
444 /*
445  * Internal form of close.
446  * Decrement reference count on
447  * file structure.
448  * Also make sure the pipe protocol
449  * does not constipate.
450  *
451  * Decrement reference count on the inode following
452  * removal to the referencing file structure.
453  * Call device handler on last close.
454  * Nouser indicates that the user isn't available to present
455  * errors to.
456  *
457  * Handling locking at this level is RIDICULOUS.
458  */
459 closef(fp, nouser, flags)
460 	register struct file *fp;
461 	int nouser, flags;
462 {
463 	register struct inode *ip;
464 	register struct mount *mp;
465 	int flag, mode;
466 	dev_t dev;
467 	register int (*cfunc)();
468 
469 	if (fp == NULL)
470 		return;
471 	if (fp->f_count > 1) {
472 		fp->f_count--;
473 		return;
474 	}
475 	if (fp->f_type == DTYPE_SOCKET) {
476 		u.u_error = soclose(fp->f_socket, nouser);
477 		if (nouser == 0 && u.u_error)
478 			return;
479 		fp->f_socket = 0;
480 		fp->f_count = 0;
481 		return;
482 	}
483 	flag = fp->f_flag;
484 	ip = fp->f_inode;
485 	dev = (dev_t)ip->i_rdev;
486 	mode = ip->i_mode & IFMT;
487 	flags &= UF_SHLOCK|UF_EXLOCK;			/* conservative */
488 	if (flags)
489 		funlocki(ip, flags);
490 	ilock(ip);
491 	iput(ip);
492 	fp->f_count = 0;
493 
494 	switch (mode) {
495 
496 	case IFCHR:
497 		cfunc = cdevsw[major(dev)].d_close;
498 		break;
499 
500 	case IFBLK:
501 		/*
502 		 * We don't want to really close the device if it is mounted
503 		 */
504 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
505 			if (mp->m_bufp != NULL && mp->m_dev == dev)
506 				return;
507 		cfunc = bdevsw[major(dev)].d_close;
508 		break;
509 
510 	default:
511 		return;
512 	}
513 	for (fp = file; fp < fileNFILE; fp++) {
514 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
515 			continue;
516 		if (fp->f_count && (ip = fp->f_inode) &&
517 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
518 			return;
519 	}
520 	if (mode == IFBLK) {
521 		/*
522 		 * On last close of a block device (that isn't mounted)
523 		 * we must invalidate any in core blocks
524 		 */
525 		bflush(dev);
526 		binval(dev);
527 	}
528 	(*cfunc)(dev, flag, fp);
529 }
530 
531 opause()
532 {
533 
534 	for (;;)
535 		sleep((caddr_t)&u, PSLEP);
536 }
537