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