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