merge in vnode changes
[unix-history] / usr / src / sys / kern / sys_generic.c
CommitLineData
da7c5cc6 1/*
46814581 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
46814581 6 * @(#)sys_generic.c 7.9 (Berkeley) %G%
da7c5cc6 7 */
ffe28cfe 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "dir.h"
12#include "user.h"
13#include "ioctl.h"
14#include "file.h"
15#include "proc.h"
16#include "uio.h"
17#include "kernel.h"
18#include "stat.h"
e0b18aec 19#include "malloc.h"
46814581
MK
20#ifdef KTRACE
21#include "ktrace.h"
22#endif
ffe28cfe
BJ
23
24/*
25 * Read system call.
26 */
27read()
28{
ffe28cfe
BJ
29 register struct a {
30 int fdes;
31 char *cbuf;
32 unsigned count;
b9429893 33 } *uap = (struct a *)u.u_ap;
32a43ee2
BJ
34 struct uio auio;
35 struct iovec aiov;
ffe28cfe 36
32a43ee2
BJ
37 aiov.iov_base = (caddr_t)uap->cbuf;
38 aiov.iov_len = uap->count;
39 auio.uio_iov = &aiov;
40 auio.uio_iovcnt = 1;
b9429893
BJ
41 rwuio(&auio, UIO_READ);
42}
43
44readv()
45{
46 register struct a {
47 int fdes;
48 struct iovec *iovp;
31286ce2 49 unsigned iovcnt;
b9429893
BJ
50 } *uap = (struct a *)u.u_ap;
51 struct uio auio;
46814581 52 struct iovec aiov[UIO_SMALLIOV], *iov;
b9429893 53
46814581
MK
54 if (uap->iovcnt > UIO_SMALLIOV) {
55 if (uap->iovcnt > UIO_MAXIOV) {
56 u.u_error = EINVAL;
57 return;
58 }
59 MALLOC(iov, struct iovec *,
60 sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
61 if (iov == NULL) {
62 u.u_error = ENOMEM;
63 return;
64 }
65 } else
66 iov = aiov;
67 auio.uio_iov = iov;
b9429893 68 auio.uio_iovcnt = uap->iovcnt;
46814581 69 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)auio.uio_iov,
31286ce2 70 uap->iovcnt * sizeof (struct iovec));
127f7d76 71 if (u.u_error)
46814581 72 goto done;
b9429893 73 rwuio(&auio, UIO_READ);
46814581
MK
74done:
75 if (iov != aiov)
76 FREE(iov, M_IOV);
ffe28cfe
BJ
77}
78
79/*
80 * Write system call
81 */
82write()
83{
ffe28cfe
BJ
84 register struct a {
85 int fdes;
86 char *cbuf;
31286ce2 87 unsigned count;
b9429893
BJ
88 } *uap = (struct a *)u.u_ap;
89 struct uio auio;
90 struct iovec aiov;
ffe28cfe 91
b9429893
BJ
92 auio.uio_iov = &aiov;
93 auio.uio_iovcnt = 1;
94 aiov.iov_base = uap->cbuf;
95 aiov.iov_len = uap->count;
96 rwuio(&auio, UIO_WRITE);
97}
98
99writev()
100{
101 register struct a {
102 int fdes;
103 struct iovec *iovp;
31286ce2 104 unsigned iovcnt;
b9429893
BJ
105 } *uap = (struct a *)u.u_ap;
106 struct uio auio;
46814581 107 struct iovec aiov[UIO_SMALLIOV], *iov;
b9429893 108
46814581
MK
109 if (uap->iovcnt > UIO_SMALLIOV) {
110 if (uap->iovcnt > UIO_MAXIOV) {
111 u.u_error = EINVAL;
112 return;
113 }
114 MALLOC(iov, struct iovec *,
115 sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
116 if (iov == NULL) {
117 u.u_error = ENOMEM;
118 return;
119 }
120 } else
121 iov = aiov;
122 auio.uio_iov = iov;
b9429893 123 auio.uio_iovcnt = uap->iovcnt;
46814581 124 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)auio.uio_iov,
31286ce2 125 uap->iovcnt * sizeof (struct iovec));
127f7d76 126 if (u.u_error)
46814581 127 goto done;
b9429893 128 rwuio(&auio, UIO_WRITE);
46814581
MK
129done:
130 if (iov != aiov)
131 FREE(iov, M_IOV);
b9429893
BJ
132}
133
134rwuio(uio, rw)
135 register struct uio *uio;
136 enum uio_rw rw;
137{
138 struct a {
139 int fdes;
140 };
141 register struct file *fp;
142 register struct iovec *iov;
b9429893 143 int i, count;
46814581
MK
144#ifdef KTRACE
145 struct iovec *ktriov = NULL;
146#endif
147
b9429893
BJ
148
149 GETF(fp, ((struct a *)u.u_ap)->fdes);
150 if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
ffe28cfe
BJ
151 u.u_error = EBADF;
152 return;
153 }
b9429893 154 uio->uio_resid = 0;
c41770c0 155 uio->uio_segflg = UIO_USERSPACE;
b9429893
BJ
156 iov = uio->uio_iov;
157 for (i = 0; i < uio->uio_iovcnt; i++) {
158 if (iov->iov_len < 0) {
159 u.u_error = EINVAL;
160 return;
161 }
162 uio->uio_resid += iov->iov_len;
163 if (uio->uio_resid < 0) {
164 u.u_error = EINVAL;
165 return;
166 }
2a0114a8 167 iov++;
b9429893
BJ
168 }
169 count = uio->uio_resid;
46814581
MK
170#ifdef KTRACE
171 /* if tracing, save a copy of iovec */
172 if (KTRPOINT(u.u_procp, KTR_GENIO)) {
173 int iovlen = uio->uio_iovcnt * sizeof (struct iovec);
174
175 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
176 if (ktriov != NULL)
177 bcopy((caddr_t)uio->uio_iov, (caddr_t)ktriov, iovlen);
178 }
179#endif
fe7f81f4
KM
180 if (setjmp(&u.u_qsave)) {
181 if (uio->uio_resid == count) {
9f49ba41 182 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
fe7f81f4
KM
183 u.u_error = EINTR;
184 else
185 u.u_eosys = RESTARTSYS;
186 }
b9429893 187 } else
88a7a62a
SL
188 u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
189 u.u_r.r_val1 = count - uio->uio_resid;
46814581
MK
190#ifdef KTRACE
191 if (ktriov != NULL) {
192 ktrgenio(u.u_procp->p_tracep, ((struct a *)u.u_ap)->fdes,
193 rw, ktriov, u.u_r.r_val1);
194 FREE(ktriov, M_TEMP);
195 }
196#endif
4147b3f6 197}
ffe28cfe
BJ
198
199/*
200 * Ioctl system call
ffe28cfe
BJ
201 */
202ioctl()
203{
204 register struct file *fp;
4b72e2f9 205 struct a {
ffe28cfe
BJ
206 int fdes;
207 int cmd;
208 caddr_t cmarg;
209 } *uap;
b9429893
BJ
210 register int com;
211 register u_int size;
e0b18aec 212 caddr_t memp = 0;
c0bb7b0e 213#define STK_PARAMS 128
08eb908c
MK
214 char stkbuf[STK_PARAMS];
215 caddr_t data = stkbuf;
ffe28cfe
BJ
216
217 uap = (struct a *)u.u_ap;
21e0a474 218 GETF(fp, uap->fdes);
ffe28cfe
BJ
219 if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
220 u.u_error = EBADF;
221 return;
222 }
4b72e2f9
SL
223 com = uap->cmd;
224
4b72e2f9 225 if (com == FIOCLEX) {
3650c37d 226 u.u_pofile[uap->fdes] |= UF_EXCLOSE;
ffe28cfe
BJ
227 return;
228 }
4b72e2f9 229 if (com == FIONCLEX) {
3650c37d 230 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
ffe28cfe
BJ
231 return;
232 }
4b72e2f9
SL
233
234 /*
235 * Interpret high order word to find
236 * amount of data to be copied to/from the
237 * user's address space.
4b72e2f9 238 */
c0bb7b0e
MK
239 size = IOCPARM_LEN(com);
240 if (size > IOCPARM_MAX) {
46814581 241 u.u_error = ENOTTY;
ffe28cfe
BJ
242 return;
243 }
08eb908c 244 if (size > sizeof (stkbuf)) {
46814581 245 memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS,
5adcb337 246 M_WAITOK);
e0b18aec 247 data = memp;
c0bb7b0e 248 }
471f17ed
SL
249 if (com&IOC_IN) {
250 if (size) {
46814581 251 u.u_error = copyin(uap->cmarg, data, (u_int)size);
e0b18aec
KM
252 if (u.u_error) {
253 if (memp)
254 free(memp, M_IOCTLOPS);
471f17ed 255 return;
e0b18aec 256 }
471f17ed
SL
257 } else
258 *(caddr_t *)data = uap->cmarg;
259 } else if ((com&IOC_OUT) && size)
260 /*
46814581
MK
261 * Zero the buffer so the user always
262 * gets back something deterministic.
471f17ed 263 */
c0bb7b0e 264 bzero(data, size);
a76b60f6
SL
265 else if (com&IOC_VOID)
266 *(caddr_t *)data = uap->cmarg;
4b72e2f9 267
88a7a62a
SL
268 switch (com) {
269
270 case FIONBIO:
271 u.u_error = fset(fp, FNDELAY, *(int *)data);
c0bb7b0e 272 break;
88a7a62a
SL
273
274 case FIOASYNC:
275 u.u_error = fset(fp, FASYNC, *(int *)data);
c0bb7b0e 276 break;
88a7a62a
SL
277
278 case FIOSETOWN:
279 u.u_error = fsetown(fp, *(int *)data);
c0bb7b0e 280 break;
4b72e2f9 281
88a7a62a
SL
282 case FIOGETOWN:
283 u.u_error = fgetown(fp, (int *)data);
c0bb7b0e
MK
284 break;
285 default:
286 if (setjmp(&u.u_qsave))
287 u.u_error = EINTR;
288 else
289 u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
290 /*
291 * Copy any data to user, size was
292 * already set and checked above.
293 */
294 if (u.u_error == 0 && (com&IOC_OUT) && size)
295 u.u_error = copyout(data, uap->cmarg, (u_int)size);
296 break;
88a7a62a 297 }
e0b18aec
KM
298 if (memp)
299 free(memp, M_IOCTLOPS);
ffe28cfe
BJ
300}
301
88a7a62a
SL
302int unselect();
303int nselcoll;
d441e5bc 304
ffe28cfe 305/*
88a7a62a 306 * Select system call.
ffe28cfe 307 */
88a7a62a
SL
308select()
309{
310 register struct uap {
311 int nd;
b8e71e77 312 fd_set *in, *ou, *ex;
88a7a62a
SL
313 struct timeval *tv;
314 } *uap = (struct uap *)u.u_ap;
b8e71e77 315 fd_set ibits[3], obits[3];
88a7a62a 316 struct timeval atv;
d441e5bc 317 int s, ncoll, ni;
88a7a62a
SL
318 label_t lqsave;
319
01b0e233
MK
320 bzero((caddr_t)ibits, sizeof(ibits));
321 bzero((caddr_t)obits, sizeof(obits));
88a7a62a
SL
322 if (uap->nd > NOFILE)
323 uap->nd = NOFILE; /* forgiving, if slightly wrong */
b8e71e77 324 ni = howmany(uap->nd, NFDBITS);
88a7a62a
SL
325
326#define getbits(name, x) \
327 if (uap->name) { \
b8e71e77 328 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
01b0e233 329 (unsigned)(ni * sizeof(fd_mask))); \
88a7a62a
SL
330 if (u.u_error) \
331 goto done; \
d441e5bc 332 }
88a7a62a
SL
333 getbits(in, 0);
334 getbits(ou, 1);
335 getbits(ex, 2);
336#undef getbits
337
338 if (uap->tv) {
339 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
340 sizeof (atv));
341 if (u.u_error)
342 goto done;
343 if (itimerfix(&atv)) {
344 u.u_error = EINVAL;
345 goto done;
346 }
c4e1f1e5 347 s = splhigh(); timevaladd(&atv, &time); splx(s);
88a7a62a
SL
348 }
349retry:
350 ncoll = nselcoll;
351 u.u_procp->p_flag |= SSEL;
d441e5bc 352 u.u_r.r_val1 = selscan(ibits, obits, uap->nd);
88a7a62a
SL
353 if (u.u_error || u.u_r.r_val1)
354 goto done;
c4e1f1e5 355 s = splhigh();
e394e134
SL
356 /* this should be timercmp(&time, &atv, >=) */
357 if (uap->tv && (time.tv_sec > atv.tv_sec ||
358 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
88a7a62a
SL
359 splx(s);
360 goto done;
361 }
362 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
88a7a62a
SL
363 splx(s);
364 goto retry;
365 }
366 u.u_procp->p_flag &= ~SSEL;
367 if (uap->tv) {
368 lqsave = u.u_qsave;
369 if (setjmp(&u.u_qsave)) {
370 untimeout(unselect, (caddr_t)u.u_procp);
371 u.u_error = EINTR;
372 splx(s);
373 goto done;
374 }
375 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
376 }
377 sleep((caddr_t)&selwait, PZERO+1);
378 if (uap->tv) {
379 u.u_qsave = lqsave;
380 untimeout(unselect, (caddr_t)u.u_procp);
381 }
382 splx(s);
383 goto retry;
384done:
b894ed59 385 u.u_procp->p_flag &= ~SSEL;
88a7a62a
SL
386#define putbits(name, x) \
387 if (uap->name) { \
b8e71e77 388 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
01b0e233 389 (unsigned)(ni * sizeof(fd_mask))); \
88a7a62a
SL
390 if (error) \
391 u.u_error = error; \
392 }
87a3ba07 393 if (u.u_error == 0) {
79f403fc
MK
394 putbits(in, 0);
395 putbits(ou, 1);
396 putbits(ex, 2);
88a7a62a 397#undef putbits
79f403fc 398 }
88a7a62a
SL
399}
400
401unselect(p)
402 register struct proc *p;
403{
c4e1f1e5 404 register int s = splhigh();
88a7a62a
SL
405
406 switch (p->p_stat) {
407
408 case SSLEEP:
409 setrun(p);
410 break;
411
412 case SSTOP:
413 unsleep(p);
414 break;
415 }
416 splx(s);
417}
418
d441e5bc 419selscan(ibits, obits, nfd)
b8e71e77 420 fd_set *ibits, *obits;
88a7a62a 421{
b8e71e77
MK
422 register int which, i, j;
423 register fd_mask bits;
88a7a62a
SL
424 int flag;
425 struct file *fp;
426 int n = 0;
427
428 for (which = 0; which < 3; which++) {
88a7a62a
SL
429 switch (which) {
430
431 case 0:
432 flag = FREAD; break;
433
434 case 1:
435 flag = FWRITE; break;
436
437 case 2:
438 flag = 0; break;
439 }
b8e71e77
MK
440 for (i = 0; i < nfd; i += NFDBITS) {
441 bits = ibits[which].fds_bits[i/NFDBITS];
d441e5bc
MK
442 while ((j = ffs(bits)) && i + --j < nfd) {
443 bits &= ~(1 << j);
444 fp = u.u_ofile[i + j];
445 if (fp == NULL) {
446 u.u_error = EBADF;
447 break;
448 }
449 if ((*fp->f_ops->fo_select)(fp, flag)) {
b8e71e77 450 FD_SET(i + j, &obits[which]);
d441e5bc
MK
451 n++;
452 }
88a7a62a
SL
453 }
454 }
455 }
456 return (n);
457}
458
ffe28cfe 459/*ARGSUSED*/
88a7a62a
SL
460seltrue(dev, flag)
461 dev_t dev;
462 int flag;
ffe28cfe
BJ
463{
464
88a7a62a 465 return (1);
ffe28cfe 466}
1edb1cf8 467
88a7a62a
SL
468selwakeup(p, coll)
469 register struct proc *p;
470 int coll;
1edb1cf8
BJ
471{
472
88a7a62a
SL
473 if (coll) {
474 nselcoll++;
475 wakeup((caddr_t)&selwait);
476 }
477 if (p) {
c4e1f1e5 478 int s = splhigh();
6bc3aba9
MK
479 if (p->p_wchan == (caddr_t)&selwait) {
480 if (p->p_stat == SSLEEP)
481 setrun(p);
482 else
483 unsleep(p);
484 } else if (p->p_flag & SSEL)
88a7a62a
SL
485 p->p_flag &= ~SSEL;
486 splx(s);
487 }
1edb1cf8 488}