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