xref: /csrg-svn/sys/kern/kern_descrip.c (revision 7653)
1 /*	kern_descrip.c	5.3	82/08/03	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/inode.h"
8 #include "../h/proc.h"
9 #include "../h/conf.h"
10 #include "../h/file.h"
11 #include "../h/inline.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 dstd()
32 {
33 
34 	u.u_r.r_val1 = NOFILE;
35 }
36 
37 dup()
38 {
39 	register struct a {
40 		int	i;
41 	} *uap = (struct a *) u.u_ap;
42 	register struct file *fp;
43 	register int j;
44 
45 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
46 
47 	fp = getf(uap->i);
48 	if (fp == 0)
49 		return;
50 	j = ufalloc();
51 	if (j < 0)
52 		return;
53 	u.u_ofile[j] = fp;
54 	fp->f_count++;
55 }
56 
57 dup2()
58 {
59 	register struct a {
60 		int	i, j;
61 	} *uap = (struct a *) u.u_ap;
62 	register struct file *fp;
63 
64 	fp = getf(uap->i);
65 	if (fp == 0)
66 		return;
67 	if (uap->j < 0 || uap->j >= NOFILE) {
68 		u.u_error = EBADF;
69 		return;
70 	}
71 	u.u_r.r_val1 = uap->j;
72 	if (uap->i == uap->j)
73 		return;
74 	if (u.u_ofile[uap->j]) {
75 		closef(u.u_ofile[uap->j], 0);
76 		if (u.u_error)
77 			return;
78 		/* u.u_ofile[uap->j] = 0; */
79 	}
80 	u.u_ofile[uap->j] = fp;
81 	fp->f_count++;
82 }
83 
84 close()
85 {
86 	register struct a {
87 		int	i;
88 	} *uap = (struct a *)u.u_ap;
89 	register struct file *fp;
90 
91 	fp = getf(uap->i);
92 	if (fp == 0)
93 		return;
94 	u.u_ofile[uap->i] = 0;
95 	closef(fp, 0);
96 	/* WHAT IF u.u_error ? */
97 }
98 
99 dtype()
100 {
101 	register struct a {
102 		int	d;
103 		struct	dtype *dtypeb;
104 	} *uap = (struct a *)u.u_ap;
105 	register struct file *fp;
106 	struct dtype adtype;
107 
108 	fp = getf(uap->d);
109 	if (fp == 0)
110 		return;
111 	adtype.dt_type = 0;		/* XXX */
112 	adtype.dt_protocol = 0;		/* XXX */
113 	if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
114 	    sizeof (struct dtype)) < 0) {
115 		u.u_error = EFAULT;
116 		return;
117 	}
118 }
119 
120 dwrap()
121 {
122 	register struct a {
123 		int	d;
124 		struct	dtype *dtypeb;
125 	} *uap = (struct a *)u.u_ap;
126 	register struct file *fp;
127 	struct dtype adtype;
128 
129 	fp = getf(uap->d);
130 	if (fp == 0)
131 		return;
132 	if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
133 	    sizeof (struct dtype)) < 0) {
134 		u.u_error = EFAULT;
135 		return;
136 	}
137 	/* DO WRAP */
138 }
139 
140 dselect()
141 {
142 
143 }
144 
145 dnblock()
146 {
147 	register struct a {
148 		int	d;
149 		int	how;
150 	} *uap = (struct a *)u.u_ap;
151 
152 	/* XXX */
153 }
154 
155 dsignal()
156 {
157 	register struct a {
158 		int	d;
159 		int	how;
160 	} *uap = (struct a *)u.u_ap;
161 
162 	/* XXX */
163 }
164 
165 int	nselcoll;
166 /*
167  * Select system call.
168  */
169 oselect()
170 {
171 	register struct uap  {
172 		int	nfd;
173 		fd_set	*rp, *wp;
174 		int	timo;
175 	} *ap = (struct uap *)u.u_ap;
176 	fd_set rd, wr;
177 	int nfds = 0, readable = 0, writeable = 0;
178 	time_t t = time;
179 	int s, tsel, ncoll, rem;
180 
181 	if (ap->nfd > NOFILE)
182 		ap->nfd = NOFILE;
183 	if (ap->nfd < 0) {
184 		u.u_error = EBADF;
185 		return;
186 	}
187 	if (ap->rp && copyin((caddr_t)ap->rp,(caddr_t)&rd,sizeof(fd_set)))
188 		return;
189 	if (ap->wp && copyin((caddr_t)ap->wp,(caddr_t)&wr,sizeof(fd_set)))
190 		return;
191 retry:
192 	ncoll = nselcoll;
193 	u.u_procp->p_flag |= SSEL;
194 	if (ap->rp)
195 		readable = selscan(ap->nfd, rd, &nfds, FREAD);
196 	if (ap->wp)
197 		writeable = selscan(ap->nfd, wr, &nfds, FWRITE);
198 	if (u.u_error)
199 		goto done;
200 	if (readable || writeable)
201 		goto done;
202 	rem = (ap->timo+999)/1000 - (time - t);
203 	if (ap->timo == 0 || rem <= 0)
204 		goto done;
205 	s = spl6();
206 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
207 		u.u_procp->p_flag &= ~SSEL;
208 		splx(s);
209 		goto retry;
210 	}
211 	u.u_procp->p_flag &= ~SSEL;
212 	tsel = tsleep((caddr_t)&selwait, PZERO+1, rem);
213 	splx(s);
214 	switch (tsel) {
215 
216 	case TS_OK:
217 		goto retry;
218 
219 	case TS_SIG:
220 		u.u_error = EINTR;
221 		return;
222 
223 	case TS_TIME:
224 		break;
225 	}
226 done:
227 	rd.fds_bits[0] = readable;
228 	wr.fds_bits[0] = writeable;
229 	s = sizeof (fd_set);
230 	if (s * NBBY > ap->nfd)
231 		s = (ap->nfd + NBBY - 1) / NBBY;
232 	u.u_r.r_val1 = nfds;
233 	if (ap->rp)
234 		(void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set));
235 	if (ap->wp)
236 		(void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set));
237 }
238 
239 selscan(nfd, fds, nfdp, flag)
240 	int nfd;
241 	fd_set fds;
242 	int *nfdp, flag;
243 {
244 	struct file *fp;
245 	struct inode *ip;
246 	register int bits;
247 	int i, able, res = 0;
248 
249 	bits = fds.fds_bits[0];
250 	while (i = ffs(bits)) {
251 		if (i > nfd)
252 			break;
253 		bits &= ~(1<<(i-1));
254 		fp = u.u_ofile[i-1];
255 		if (fp == NULL) {
256 			u.u_error = EBADF;
257 			return (0);
258 		}
259 		if (fp->f_type == DTYPE_SOCKET)
260 			able = soselect(fp->f_socket, flag);
261 		else {
262 			ip = fp->f_inode;
263 			switch (ip->i_mode & IFMT) {
264 
265 			case IFCHR:
266 				able =
267 				    (*cdevsw[major(ip->i_rdev)].d_select)
268 					(ip->i_rdev, flag);
269 				break;
270 
271 			case IFBLK:
272 			case IFREG:
273 			case IFDIR:
274 				able = 1;
275 				break;
276 			}
277 
278 		}
279 		if (able) {
280 			res |= (1<<(i-1));
281 			(*nfdp)++;
282 		}
283 	}
284 	return (res);
285 }
286 
287 /*ARGSUSED*/
288 seltrue(dev, flag)
289 	dev_t dev;
290 	int flag;
291 {
292 
293 	return (1);
294 }
295 
296 selwakeup(p, coll)
297 	register struct proc *p;
298 	int coll;
299 {
300 	int s;
301 
302 	if (coll) {
303 		nselcoll++;
304 		wakeup((caddr_t)&selwait);
305 	}
306 	if (p) {
307 		if (p->p_wchan == (caddr_t)&selwait)
308 			setrun(p);
309 		else {
310 			s = spl6();
311 			if (p->p_flag & SSEL)
312 				p->p_flag &= ~SSEL;
313 			splx(s);
314 		}
315 	}
316 }
317 
318 
319 /*
320  * Allocate a user file descriptor.
321  */
322 ufalloc()
323 {
324 	register i;
325 
326 	for (i=0; i<NOFILE; i++)
327 		if (u.u_ofile[i] == NULL) {
328 			u.u_r.r_val1 = i;
329 			u.u_pofile[i] = 0;
330 			return (i);
331 		}
332 	u.u_error = EMFILE;
333 	return (-1);
334 }
335 
336 struct	file *lastf;
337 /*
338  * Allocate a user file descriptor
339  * and a file structure.
340  * Initialize the descriptor
341  * to point at the file structure.
342  */
343 struct file *
344 falloc()
345 {
346 	register struct file *fp;
347 	register i;
348 
349 	i = ufalloc();
350 	if (i < 0)
351 		return (NULL);
352 	if (lastf == 0)
353 		lastf = file;
354 	for (fp = lastf; fp < fileNFILE; fp++)
355 		if (fp->f_count == 0)
356 			goto slot;
357 	for (fp = file; fp < lastf; fp++)
358 		if (fp->f_count == 0)
359 			goto slot;
360 	tablefull("file");
361 	u.u_error = ENFILE;
362 	return (NULL);
363 slot:
364 	u.u_ofile[i] = fp;
365 	fp->f_count++;
366 	fp->f_offset = 0;
367 	fp->f_inode = 0;
368 	lastf = fp + 1;
369 	return (fp);
370 }
371 /*
372  * Convert a user supplied file descriptor into a pointer
373  * to a file structure.  Only task is to check range of the descriptor.
374  * Critical paths should use the GETF macro, defined in inline.h.
375  */
376 struct file *
377 getf(f)
378 	register int f;
379 {
380 	register struct file *fp;
381 
382 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
383 		u.u_error = EBADF;
384 		return (NULL);
385 	}
386 	return (fp);
387 }
388 
389 /*
390  * Internal form of close.
391  * Decrement reference count on
392  * file structure.
393  * Also make sure the pipe protocol
394  * does not constipate.
395  *
396  * Decrement reference count on the inode following
397  * removal to the referencing file structure.
398  * Call device handler on last close.
399  * Nouser indicates that the user isn't available to present
400  * errors to.
401  */
402 closef(fp, nouser)
403 	register struct file *fp;
404 {
405 	register struct inode *ip;
406 	register struct mount *mp;
407 	int flag, mode;
408 	dev_t dev;
409 	register int (*cfunc)();
410 
411 	if (fp == NULL)
412 		return;
413 	if (fp->f_count > 1) {
414 		fp->f_count--;
415 		return;
416 	}
417 	if (fp->f_type == DTYPE_SOCKET) {
418 		u.u_error = 0;			/* XXX */
419 		soclose(fp->f_socket, nouser);
420 		if (nouser == 0 && u.u_error)
421 			return;
422 		fp->f_socket = 0;
423 		fp->f_count = 0;
424 		return;
425 	}
426 	flag = fp->f_flag;
427 	ip = fp->f_inode;
428 	dev = (dev_t)ip->i_rdev;
429 	mode = ip->i_mode & IFMT;
430 	ilock(ip);
431 	iput(ip);
432 	fp->f_count = 0;
433 
434 	switch (mode) {
435 
436 	case IFCHR:
437 		cfunc = cdevsw[major(dev)].d_close;
438 		break;
439 
440 	case IFBLK:
441 		/*
442 		 * We don't want to really close the device if it is mounted
443 		 */
444 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
445 			if (mp->m_bufp != NULL && mp->m_dev == dev)
446 				return;
447 		cfunc = bdevsw[major(dev)].d_close;
448 		break;
449 
450 	default:
451 		return;
452 	}
453 	for (fp = file; fp < fileNFILE; fp++) {
454 		if (fp->f_type == DTYPE_SOCKET)		/* XXX */
455 			continue;
456 		if (fp->f_count && (ip = fp->f_inode) &&
457 		    ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
458 			return;
459 	}
460 	if (mode == IFBLK) {
461 		/*
462 		 * On last close of a block device (that isn't mounted)
463 		 * we must invalidate any in core blocks
464 		 */
465 		bflush(dev);
466 		binval(dev);
467 	}
468 	(*cfunc)(dev, flag, fp);
469 }
470 
471 #ifdef CAD
472 /*
473  * chfile -- change all references to the inode named by
474  *	     device/inum to the file referred to by fd.
475  * Used by init to remove all references to the device.
476  */
477 chfile()
478 {
479 	register struct file *fp;
480 	register struct inode *from;
481 	register struct inode *to;
482 	off_t offset;
483 	dev_t dev;
484 	int rw;
485 	struct a {
486 		int	device;		/* actually dev_t */
487 		int	inum;		/* actually ino_t */
488 		int	fd;
489 	} *uap;
490 
491 	if (!suser()) {
492 		u.u_error = EPERM;
493 		return;
494 	}
495 	uap = (struct a *) u.u_ap;
496 	fp = getf(uap->fd);
497 	if (fp == NULL) {
498 		u.u_error = EBADF;
499 		return;
500 	}
501 	if (fp->f_type == DTYPE_SOCKET) {
502 		u.u_error = EINVAL;
503 		return;
504 	}
505 	for (from = &inode[0]; from < &inode[ninode]; from++)
506 		if (from->i_number == (ino_t)uap->inum
507 		   && from->i_dev == (dev_t)uap->device)
508 			break;
509 	if (from >= &inode[ninode]) {
510 		u.u_error = ENXIO;
511 		return;
512 	}
513 	offset = fp->f_offset;
514 	to = fp->f_inode;
515 	from->i_count++;
516 	for (fp = &file[0]; fp < &file[nfile]; fp++) {
517 		if (fp->f_count > 0 && fp->f_inode == from) {
518 			fp->f_inode = to;
519 			to->i_count++;
520 			fp->f_offset = offset;
521 			rw |= fp->f_flag & FWRITE;
522 			iput(from);
523 		}
524 	}
525 	/*
526 	 * This inode is no longer referenced.
527 	 * Switch out to the appropriate close
528 	 * routine, if required
529 	 */
530 	dev = (dev_t)from->i_un.i_rdev;
531 	switch(from->i_mode & IFMT) {
532 
533 	case IFCHR:
534 		(*cdevsw[major(dev)].d_close)(dev, rw);
535 		break;
536 
537 	case IFBLK:
538 		(*bdevsw[major(dev)].d_close)(dev, rw);
539 		break;
540 
541 	default:
542 		break;
543 	}
544 	iput(from);
545 }
546 #endif
547