ignore bogus (large) return values from read
[unix-history] / usr / src / sys / kern / kern_descrip.c
... / ...
CommitLineData
1/* kern_descrip.c 5.23 83/01/17 */
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/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 */
31getdtablesize()
32{
33
34 u.u_r.r_val1 = NOFILE;
35}
36
37getdprop()
38{
39 register struct a {
40 int d;
41 struct dtype *dtypeb;
42 } *uap = (struct a *)u.u_ap;
43 register struct file *fp;
44 struct dtype adtype;
45
46 fp = getf(uap->d);
47 if (fp == 0)
48 return;
49 adtype.dt_type = 0; /* XXX */
50 adtype.dt_protocol = 0; /* XXX */
51 u.u_error = copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
52 sizeof (struct dtype));
53 if (u.u_error)
54 return;
55}
56
57getdopt()
58{
59
60}
61
62setdopt()
63{
64
65}
66
67dup()
68{
69 register struct a {
70 int i;
71 } *uap = (struct a *) u.u_ap;
72 struct file *fp;
73 int j;
74
75 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */
76
77 fp = getf(uap->i);
78 if (fp == 0)
79 return;
80 j = ufalloc();
81 if (j < 0)
82 return;
83 dupit(j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK));
84}
85
86dup2()
87{
88 register struct a {
89 int i, j;
90 } *uap = (struct a *) u.u_ap;
91 register struct file *fp;
92
93 fp = getf(uap->i);
94 if (fp == 0)
95 return;
96 if (uap->j < 0 || uap->j >= NOFILE) {
97 u.u_error = EBADF;
98 return;
99 }
100 u.u_r.r_val1 = uap->j;
101 if (uap->i == uap->j)
102 return;
103 if (u.u_ofile[uap->j]) {
104 if (u.u_pofile[uap->j] & UF_MAPPED)
105 munmapfd(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] & (UF_SHLOCK|UF_EXLOCK));
113}
114
115dupit(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&UF_SHLOCK)
125 fp->f_inode->i_shlockc++;
126 if (lockflags&UF_EXLOCK)
127 fp->f_inode->i_exlockc++;
128}
129
130close()
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 if (u.u_pofile[uap->i] & UF_MAPPED)
141 munmapfd(uap->i);
142 closef(fp, 0, u.u_pofile[uap->i]);
143 /* WHAT IF u.u_error ? */
144 u.u_ofile[uap->i] = NULL;
145 u.u_pofile[uap->i] = 0;
146}
147
148wrap()
149{
150 register struct a {
151 int d;
152 struct dtype *dtypeb;
153 } *uap = (struct a *)u.u_ap;
154 register struct file *fp;
155 struct dtype adtype;
156
157 fp = getf(uap->d);
158 if (fp == 0)
159 return;
160 u.u_error = copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
161 sizeof (struct dtype));
162 if (u.u_error)
163 return;
164 /* DO WRAP */
165}
166
167int unselect();
168int nselcoll;
169/*
170 * Select system call.
171 */
172select()
173{
174 register struct uap {
175 int nd;
176 long *in;
177 long *ou;
178 long *ex;
179 struct timeval *tv;
180 } *uap = (struct uap *)u.u_ap;
181 int ibits[3], obits[3];
182 struct timeval atv;
183 int s, ncoll;
184 label_t lqsave;
185
186 obits[0] = obits[1] = obits[2] = 0;
187 if (uap->nd > NOFILE)
188 uap->nd = NOFILE; /* forgiving, if slightly wrong */
189
190#define getbits(name, x) \
191 if (uap->name) { \
192 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
193 sizeof (ibits[x])); \
194 if (u.u_error) \
195 goto done; \
196 } else \
197 ibits[x] = 0;
198 getbits(in, 0);
199 getbits(ou, 1);
200 getbits(ex, 2);
201#undef getbits
202
203 if (uap->tv) {
204 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
205 sizeof (atv));
206 if (u.u_error)
207 goto done;
208 if (itimerfix(&atv)) {
209 u.u_error = EINVAL;
210 goto done;
211 }
212 s = spl7(); timevaladd(&atv, &time); splx(s);
213 }
214retry:
215 ncoll = nselcoll;
216 u.u_procp->p_flag |= SSEL;
217 u.u_r.r_val1 = selscan(ibits, obits);
218 if (u.u_error || u.u_r.r_val1)
219 goto done;
220 s = spl6();
221 if (uap->tv && timercmp(&time, &atv, >=)) {
222 splx(s);
223 goto done;
224 }
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 if (uap->tv) {
232 lqsave = u.u_qsave;
233 if (setjmp(&u.u_qsave)) {
234 untimeout(unselect, (caddr_t)u.u_procp);
235 u.u_error = EINTR;
236 splx(s);
237 goto done;
238 }
239 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
240 }
241 sleep((caddr_t)&selwait, PZERO+1);
242 if (uap->tv) {
243 u.u_qsave = lqsave;
244 untimeout(unselect, (caddr_t)u.u_procp);
245 }
246 splx(s);
247 goto retry;
248done:
249#define putbits(name, x) \
250 if (uap->name) { \
251 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
252 sizeof (obits[x])); \
253 if (error) \
254 u.u_error = error; \
255 }
256 putbits(in, 0);
257 putbits(ou, 1);
258 putbits(ex, 2);
259#undef putbits
260}
261
262unselect(p)
263 register struct proc *p;
264{
265 register int s = spl6();
266
267 switch (p->p_stat) {
268
269 case SSLEEP:
270 setrun(p);
271 break;
272
273 case SSTOP:
274 unsleep(p);
275 break;
276 }
277 splx(s);
278}
279
280selscan(ibits, obits)
281 int *ibits, *obits;
282{
283 register int which, bits, i;
284 int flag;
285 struct file *fp;
286 int able;
287 struct inode *ip;
288 int n = 0;
289
290 for (which = 0; which < 3; which++) {
291 bits = ibits[which];
292 obits[which] = 0;
293 switch (which) {
294
295 case 0:
296 flag = FREAD; break;
297
298 case 1:
299 flag = FWRITE; break;
300
301 case 2:
302 flag = 0; break;
303 }
304 while (i = ffs(bits)) {
305 bits &= ~(1<<(i-1));
306 fp = u.u_ofile[i-1];
307 if (fp == NULL) {
308 u.u_error = EBADF;
309 break;
310 }
311 if (fp->f_type == DTYPE_SOCKET)
312 able = soselect(fp->f_socket, flag);
313 else {
314 ip = fp->f_inode;
315 switch (ip->i_mode & IFMT) {
316
317 case IFCHR:
318 able =
319 (*cdevsw[major(ip->i_rdev)].d_select)
320 (ip->i_rdev, flag);
321 break;
322
323 case IFBLK:
324 case IFREG:
325 case IFDIR:
326 able = 1;
327 break;
328 }
329
330 }
331 if (able) {
332 obits[which] |= (1<<(i-1));
333 n++;
334 }
335 }
336 }
337 return (n);
338}
339
340/*ARGSUSED*/
341seltrue(dev, flag)
342 dev_t dev;
343 int flag;
344{
345
346 return (1);
347}
348
349selwakeup(p, coll)
350 register struct proc *p;
351 int coll;
352{
353
354 if (coll) {
355 nselcoll++;
356 wakeup((caddr_t)&selwait);
357 }
358 if (p) {
359 int s = spl6();
360 if (p->p_wchan == (caddr_t)&selwait)
361 setrun(p);
362 else if (p->p_flag & SSEL)
363 p->p_flag &= ~SSEL;
364 splx(s);
365 }
366}
367
368revoke()
369{
370
371 /* XXX */
372}
373
374/*
375 * Allocate a user file descriptor.
376 */
377ufalloc()
378{
379 register i;
380
381 for (i=0; i<NOFILE; i++)
382 if (u.u_ofile[i] == NULL) {
383 u.u_r.r_val1 = i;
384 u.u_pofile[i] = 0;
385 return (i);
386 }
387 u.u_error = EMFILE;
388 return (-1);
389}
390
391struct file *lastf;
392/*
393 * Allocate a user file descriptor
394 * and a file structure.
395 * Initialize the descriptor
396 * to point at the file structure.
397 */
398struct file *
399falloc()
400{
401 register struct file *fp;
402 register i;
403
404 i = ufalloc();
405 if (i < 0)
406 return (NULL);
407 if (lastf == 0)
408 lastf = file;
409 for (fp = lastf; fp < fileNFILE; fp++)
410 if (fp->f_count == 0)
411 goto slot;
412 for (fp = file; fp < lastf; fp++)
413 if (fp->f_count == 0)
414 goto slot;
415 tablefull("file");
416 u.u_error = ENFILE;
417 return (NULL);
418slot:
419 u.u_ofile[i] = fp;
420 fp->f_count++;
421 fp->f_offset = 0;
422 fp->f_inode = 0;
423 lastf = fp + 1;
424 return (fp);
425}
426/*
427 * Convert a user supplied file descriptor into a pointer
428 * to a file structure. Only task is to check range of the descriptor.
429 * Critical paths should use the GETF macro, defined in inline.h.
430 */
431struct file *
432getf(f)
433 register int f;
434{
435 register struct file *fp;
436
437 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
438 u.u_error = EBADF;
439 return (NULL);
440 }
441 return (fp);
442}
443
444/*
445 * Internal form of close.
446 * Decrement reference count on
447 * file structure.
448 * Also make sure the pipe protocol
449 * does not constipate.
450 *
451 * Decrement reference count on the inode following
452 * removal to the referencing file structure.
453 * Call device handler on last close.
454 * Nouser indicates that the user isn't available to present
455 * errors to.
456 *
457 * Handling locking at this level is RIDICULOUS.
458 */
459closef(fp, nouser, flags)
460 register struct file *fp;
461 int nouser, flags;
462{
463 register struct inode *ip;
464 register struct mount *mp;
465 int flag, mode;
466 dev_t dev;
467 register int (*cfunc)();
468
469 if (fp == NULL)
470 return;
471 if (fp->f_count > 1) {
472 fp->f_count--;
473 return;
474 }
475 if (fp->f_type == DTYPE_SOCKET) {
476 u.u_error = soclose(fp->f_socket, nouser);
477 if (nouser == 0 && u.u_error)
478 return;
479 fp->f_socket = 0;
480 fp->f_count = 0;
481 return;
482 }
483 flag = fp->f_flag;
484 ip = fp->f_inode;
485 dev = (dev_t)ip->i_rdev;
486 mode = ip->i_mode & IFMT;
487 flags &= UF_SHLOCK|UF_EXLOCK; /* conservative */
488 if (flags)
489 funlocki(ip, flags);
490 ilock(ip);
491 iput(ip);
492 fp->f_count = 0;
493
494 switch (mode) {
495
496 case IFCHR:
497 cfunc = cdevsw[major(dev)].d_close;
498 break;
499
500 case IFBLK:
501 /*
502 * We don't want to really close the device if it is mounted
503 */
504 for (mp = mount; mp < &mount[NMOUNT]; mp++)
505 if (mp->m_bufp != NULL && mp->m_dev == dev)
506 return;
507 cfunc = bdevsw[major(dev)].d_close;
508 break;
509
510 default:
511 return;
512 }
513 for (fp = file; fp < fileNFILE; fp++) {
514 if (fp->f_type == DTYPE_SOCKET) /* XXX */
515 continue;
516 if (fp->f_count && (ip = fp->f_inode) &&
517 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
518 return;
519 }
520 if (mode == IFBLK) {
521 /*
522 * On last close of a block device (that isn't mounted)
523 * we must invalidate any in core blocks
524 */
525 bflush(dev);
526 binval(dev);
527 }
528 (*cfunc)(dev, flag, fp);
529}
530
531opause()
532{
533
534 for (;;)
535 sleep((caddr_t)&u, PSLEP);
536}