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