ignore bogus (large) return values from read
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
e00b4896 1/* kern_descrip.c 5.23 83/01/17 */
40056b21
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
3ebb7a40 7#include "../h/kernel.h"
40056b21
BJ
8#include "../h/inode.h"
9#include "../h/proc.h"
40056b21 10#include "../h/conf.h"
40056b21 11#include "../h/file.h"
40056b21
BJ
12#include "../h/socket.h"
13#include "../h/socketvar.h"
4147b3f6
BJ
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 */
40056b21
BJ
27
28/*
4147b3f6 29 * System calls on descriptors.
40056b21 30 */
3ebb7a40 31getdtablesize()
4147b3f6
BJ
32{
33
34 u.u_r.r_val1 = NOFILE;
35}
36
27b91f59
BJ
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 */
127f7d76
SL
51 u.u_error = copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
52 sizeof (struct dtype));
53 if (u.u_error)
27b91f59 54 return;
27b91f59
BJ
55}
56
57getdopt()
58{
59
60}
61
62setdopt()
63{
64
65}
66
40056b21
BJ
67dup()
68{
4147b3f6
BJ
69 register struct a {
70 int i;
71 } *uap = (struct a *) u.u_ap;
a81e9a81
SL
72 struct file *fp;
73 int j;
4147b3f6
BJ
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;
3650c37d 83 dupit(j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK));
4147b3f6
BJ
84}
85
86dup2()
87{
40056b21 88 register struct a {
4147b3f6
BJ
89 int i, j;
90 } *uap = (struct a *) u.u_ap;
91 register struct file *fp;
40056b21 92
4147b3f6
BJ
93 fp = getf(uap->i);
94 if (fp == 0)
95 return;
96 if (uap->j < 0 || uap->j >= NOFILE) {
97 u.u_error = EBADF;
40056b21 98 return;
40056b21 99 }
4147b3f6
BJ
100 u.u_r.r_val1 = uap->j;
101 if (uap->i == uap->j)
102 return;
103 if (u.u_ofile[uap->j]) {
67fc76c5
BJ
104 if (u.u_pofile[uap->j] & UF_MAPPED)
105 munmapfd(uap->j);
a81e9a81 106 closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]);
40056b21
BJ
107 if (u.u_error)
108 return;
4147b3f6 109 /* u.u_ofile[uap->j] = 0; */
a81e9a81 110 /* u.u_pofile[uap->j] = 0; */
4147b3f6 111 }
3650c37d 112 dupit(uap->j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK));
a81e9a81
SL
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;
4147b3f6 123 fp->f_count++;
3650c37d 124 if (lockflags&UF_SHLOCK)
4f083fd7 125 fp->f_inode->i_shlockc++;
3650c37d 126 if (lockflags&UF_EXLOCK)
4f083fd7 127 fp->f_inode->i_exlockc++;
4147b3f6
BJ
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;
67fc76c5
BJ
140 if (u.u_pofile[uap->i] & UF_MAPPED)
141 munmapfd(uap->i);
a81e9a81 142 closef(fp, 0, u.u_pofile[uap->i]);
4147b3f6 143 /* WHAT IF u.u_error ? */
a81e9a81
SL
144 u.u_ofile[uap->i] = NULL;
145 u.u_pofile[uap->i] = 0;
4147b3f6
BJ
146}
147
3ebb7a40 148wrap()
4147b3f6
BJ
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;
127f7d76
SL
160 u.u_error = copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
161 sizeof (struct dtype));
162 if (u.u_error)
4147b3f6 163 return;
4147b3f6
BJ
164 /* DO WRAP */
165}
166
12438177 167int unselect();
40056b21
BJ
168int nselcoll;
169/*
170 * Select system call.
171 */
27b91f59 172select()
40056b21
BJ
173{
174 register struct uap {
e42abae7
BJ
175 int nd;
176 long *in;
177 long *ou;
178 long *ex;
3ebb7a40
BJ
179 struct timeval *tv;
180 } *uap = (struct uap *)u.u_ap;
12438177
BJ
181 int ibits[3], obits[3];
182 struct timeval atv;
a8d3bf7f 183 int s, ncoll;
12438177 184 label_t lqsave;
40056b21 185
ea795ba9 186 obits[0] = obits[1] = obits[2] = 0;
75c65d6e
BJ
187 if (uap->nd > NOFILE)
188 uap->nd = NOFILE; /* forgiving, if slightly wrong */
e42abae7
BJ
189
190#define getbits(name, x) \
191 if (uap->name) { \
127f7d76
SL
192 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
193 sizeof (ibits[x])); \
194 if (u.u_error) \
ea795ba9 195 goto done; \
e42abae7
BJ
196 } else \
197 ibits[x] = 0;
198 getbits(in, 0);
199 getbits(ou, 1);
200 getbits(ex, 2);
201#undef getbits
202
3ebb7a40 203 if (uap->tv) {
127f7d76
SL
204 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
205 sizeof (atv));
206 if (u.u_error)
ea795ba9 207 goto done;
12438177
BJ
208 if (itimerfix(&atv)) {
209 u.u_error = EINVAL;
ea795ba9 210 goto done;
12438177
BJ
211 }
212 s = spl7(); timevaladd(&atv, &time); splx(s);
213 }
40056b21
BJ
214retry:
215 ncoll = nselcoll;
216 u.u_procp->p_flag |= SSEL;
12438177 217 u.u_r.r_val1 = selscan(ibits, obits);
ea795ba9 218 if (u.u_error || u.u_r.r_val1)
40056b21
BJ
219 goto done;
220 s = spl6();
e42abae7 221 if (uap->tv && timercmp(&time, &atv, >=)) {
12438177
BJ
222 splx(s);
223 goto done;
224 }
40056b21
BJ
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;
12438177
BJ
231 if (uap->tv) {
232 lqsave = u.u_qsave;
233 if (setjmp(&u.u_qsave)) {
b32450f4 234 untimeout(unselect, (caddr_t)u.u_procp);
12438177
BJ
235 u.u_error = EINTR;
236 splx(s);
ea795ba9 237 goto done;
12438177 238 }
b32450f4 239 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
12438177
BJ
240 }
241 sleep((caddr_t)&selwait, PZERO+1);
242 if (uap->tv) {
243 u.u_qsave = lqsave;
b32450f4 244 untimeout(unselect, (caddr_t)u.u_procp);
12438177 245 }
40056b21 246 splx(s);
12438177
BJ
247 goto retry;
248done:
e42abae7
BJ
249#define putbits(name, x) \
250 if (uap->name) { \
127f7d76
SL
251 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
252 sizeof (obits[x])); \
253 if (error) \
254 u.u_error = error; \
12438177 255 }
e42abae7
BJ
256 putbits(in, 0);
257 putbits(ou, 1);
258 putbits(ex, 2);
259#undef putbits
12438177
BJ
260}
261
262unselect(p)
263 register struct proc *p;
264{
265 register int s = spl6();
40056b21 266
12438177
BJ
267 switch (p->p_stat) {
268
269 case SSLEEP:
270 setrun(p);
271 break;
272
273 case SSTOP:
274 unsleep(p);
40056b21
BJ
275 break;
276 }
12438177 277 splx(s);
40056b21
BJ
278}
279
12438177
BJ
280selscan(ibits, obits)
281 int *ibits, *obits;
40056b21 282{
12438177
BJ
283 register int which, bits, i;
284 int flag;
40056b21 285 struct file *fp;
12438177 286 int able;
40056b21 287 struct inode *ip;
12438177 288 int n = 0;
40056b21 289
12438177
BJ
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;
40056b21 297
12438177
BJ
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;
40056b21
BJ
309 break;
310 }
12438177
BJ
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 }
4147b3f6 329
12438177
BJ
330 }
331 if (able) {
332 obits[which] |= (1<<(i-1));
333 n++;
334 }
40056b21
BJ
335 }
336 }
12438177 337 return (n);
40056b21
BJ
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{
40056b21
BJ
353
354 if (coll) {
355 nselcoll++;
356 wakeup((caddr_t)&selwait);
357 }
358 if (p) {
19977caf 359 int s = spl6();
40056b21
BJ
360 if (p->p_wchan == (caddr_t)&selwait)
361 setrun(p);
19977caf
SL
362 else if (p->p_flag & SSEL)
363 p->p_flag &= ~SSEL;
364 splx(s);
40056b21
BJ
365 }
366}
367
3ebb7a40
BJ
368revoke()
369{
370
371 /* XXX */
372}
373
40056b21 374/*
4147b3f6 375 * Allocate a user file descriptor.
40056b21 376 */
4147b3f6
BJ
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;
40056b21
BJ
434{
435 register struct file *fp;
40056b21 436
4147b3f6
BJ
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.
a81e9a81
SL
456 *
457 * Handling locking at this level is RIDICULOUS.
4147b3f6 458 */
a81e9a81 459closef(fp, nouser, flags)
4147b3f6 460 register struct file *fp;
a81e9a81 461 int nouser, flags;
4147b3f6
BJ
462{
463 register struct inode *ip;
464 register struct mount *mp;
465 int flag, mode;
466 dev_t dev;
467 register int (*cfunc)();
468
40056b21
BJ
469 if (fp == NULL)
470 return;
4147b3f6
BJ
471 if (fp->f_count > 1) {
472 fp->f_count--;
40056b21
BJ
473 return;
474 }
4147b3f6 475 if (fp->f_type == DTYPE_SOCKET) {
6e7edb25 476 u.u_error = soclose(fp->f_socket, nouser);
4147b3f6
BJ
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;
3650c37d 487 flags &= UF_SHLOCK|UF_EXLOCK; /* conservative */
a81e9a81
SL
488 if (flags)
489 funlocki(ip, flags);
4147b3f6
BJ
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;
4147b3f6
BJ
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}
8d528261
BJ
530
531opause()
532{
533
534 for (;;)
535 sleep((caddr_t)&u, PSLEP);
536}