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