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