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