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