|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)sys_generic.c 7.30 (Berkeley) 5/30/91
34: */
35:
36: #include "param.h"
37: #include "systm.h"
38: #include "filedesc.h"
39: #include "ioctl.h"
40: #include "file.h"
41: #include "socketvar.h"
42: #include "proc.h"
43: #include "uio.h"
44: #include "kernel.h"
45: #include "stat.h"
46: #include "malloc.h"
47: #ifdef KTRACE
48: #include "ktrace.h"
49: #endif
50:
51: /*
52: * Read system call.
53: */
54: /* ARGSUSED */
55: read(p, uap, retval)
56: struct proc *p;
57: register struct args {
58: int fdes;
59: char *cbuf;
60: unsigned count;
61: } *uap;
62: int *retval;
63: {
64: register struct file *fp;
65: register struct filedesc *fdp = p->p_fd;
66: struct uio auio;
67: struct iovec aiov;
68: long cnt, error = 0;
69: #ifdef KTRACE
70: struct iovec ktriov;
71: #endif
72:
73: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
74: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
75: (fp->f_flag & FREAD) == 0)
76: return (EBADF);
77: aiov.iov_base = (caddr_t)uap->cbuf;
78: aiov.iov_len = uap->count;
79: auio.uio_iov = &aiov;
80: auio.uio_iovcnt = 1;
81: auio.uio_resid = uap->count;
82: auio.uio_rw = UIO_READ;
83: auio.uio_segflg = UIO_USERSPACE;
84: auio.uio_procp = p;
85: #ifdef KTRACE
86: /*
87: * if tracing, save a copy of iovec
88: */
89: if (KTRPOINT(p, KTR_GENIO))
90: ktriov = aiov;
91: #endif
92: cnt = uap->count;
93: if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
94: if (auio.uio_resid != cnt && (error == ERESTART ||
95: error == EINTR || error == EWOULDBLOCK))
96: error = 0;
97: cnt -= auio.uio_resid;
98: #ifdef KTRACE
99: if (KTRPOINT(p, KTR_GENIO) && error == 0)
100: ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
101: #endif
102: *retval = cnt;
103: return (error);
104: }
105:
106: /*
107: * Scatter read system call.
108: */
109: /* ARGSUSED */
110: readv(p, uap, retval)
111: struct proc *p;
112: register struct args {
113: int fdes;
114: struct iovec *iovp;
115: unsigned iovcnt;
116: } *uap;
117: int *retval;
118: {
119: register struct file *fp;
120: register struct filedesc *fdp = p->p_fd;
121: struct uio auio;
122: register struct iovec *iov;
123: struct iovec *saveiov;
124: struct iovec aiov[UIO_SMALLIOV];
125: long i, cnt, error = 0;
126: unsigned iovlen;
127: #ifdef KTRACE
128: struct iovec *ktriov = NULL;
129: #endif
130:
131: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
132: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
133: (fp->f_flag & FREAD) == 0)
134: return (EBADF);
135: /* note: can't use iovlen until iovcnt is validated */
136: iovlen = uap->iovcnt * sizeof (struct iovec);
137: if (uap->iovcnt > UIO_SMALLIOV) {
138: if (uap->iovcnt > UIO_MAXIOV)
139: return (EINVAL);
140: MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
141: saveiov = iov;
142: } else
143: iov = aiov;
144: auio.uio_iov = iov;
145: auio.uio_iovcnt = uap->iovcnt;
146: auio.uio_rw = UIO_READ;
147: auio.uio_segflg = UIO_USERSPACE;
148: auio.uio_procp = p;
149: if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
150: goto done;
151: auio.uio_resid = 0;
152: for (i = 0; i < uap->iovcnt; i++) {
153: if (iov->iov_len < 0) {
154: error = EINVAL;
155: goto done;
156: }
157: auio.uio_resid += iov->iov_len;
158: if (auio.uio_resid < 0) {
159: error = EINVAL;
160: goto done;
161: }
162: iov++;
163: }
164: #ifdef KTRACE
165: /*
166: * if tracing, save a copy of iovec
167: */
168: if (KTRPOINT(p, KTR_GENIO)) {
169: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
170: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
171: }
172: #endif
173: cnt = auio.uio_resid;
174: if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
175: if (auio.uio_resid != cnt && (error == ERESTART ||
176: error == EINTR || error == EWOULDBLOCK))
177: error = 0;
178: cnt -= auio.uio_resid;
179: #ifdef KTRACE
180: if (ktriov != NULL) {
181: if (error == 0)
182: ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
183: cnt, error);
184: FREE(ktriov, M_TEMP);
185: }
186: #endif
187: *retval = cnt;
188: done:
189: if (uap->iovcnt > UIO_SMALLIOV)
190: FREE(saveiov, M_IOV);
191: return (error);
192: }
193:
194: /*
195: * Write system call
196: */
197: write(p, uap, retval)
198: struct proc *p;
199: register struct args {
200: int fdes;
201: char *cbuf;
202: unsigned count;
203: } *uap;
204: int *retval;
205: {
206: register struct file *fp;
207: register struct filedesc *fdp = p->p_fd;
208: struct uio auio;
209: struct iovec aiov;
210: long cnt, error = 0;
211: #ifdef KTRACE
212: struct iovec ktriov;
213: #endif
214:
215: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
216: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
217: (fp->f_flag & FWRITE) == 0)
218: return (EBADF);
219: aiov.iov_base = (caddr_t)uap->cbuf;
220: aiov.iov_len = uap->count;
221: auio.uio_iov = &aiov;
222: auio.uio_iovcnt = 1;
223: auio.uio_resid = uap->count;
224: auio.uio_rw = UIO_WRITE;
225: auio.uio_segflg = UIO_USERSPACE;
226: auio.uio_procp = p;
227: #ifdef KTRACE
228: /*
229: * if tracing, save a copy of iovec
230: */
231: if (KTRPOINT(p, KTR_GENIO))
232: ktriov = aiov;
233: #endif
234: cnt = uap->count;
235: if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
236: if (auio.uio_resid != cnt && (error == ERESTART ||
237: error == EINTR || error == EWOULDBLOCK))
238: error = 0;
239: if (error == EPIPE)
240: psignal(p, SIGPIPE);
241: }
242: cnt -= auio.uio_resid;
243: #ifdef KTRACE
244: if (KTRPOINT(p, KTR_GENIO) && error == 0)
245: ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
246: &ktriov, cnt, error);
247: #endif
248: *retval = cnt;
249: return (error);
250: }
251:
252: /*
253: * Gather write system call
254: */
255: writev(p, uap, retval)
256: struct proc *p;
257: register struct args {
258: int fdes;
259: struct iovec *iovp;
260: unsigned iovcnt;
261: } *uap;
262: int *retval;
263: {
264: register struct file *fp;
265: register struct filedesc *fdp = p->p_fd;
266: struct uio auio;
267: register struct iovec *iov;
268: struct iovec *saveiov;
269: struct iovec aiov[UIO_SMALLIOV];
270: long i, cnt, error = 0;
271: unsigned iovlen;
272: #ifdef KTRACE
273: struct iovec *ktriov = NULL;
274: #endif
275:
276: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
277: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
278: (fp->f_flag & FWRITE) == 0)
279: return (EBADF);
280: /* note: can't use iovlen until iovcnt is validated */
281: iovlen = uap->iovcnt * sizeof (struct iovec);
282: if (uap->iovcnt > UIO_SMALLIOV) {
283: if (uap->iovcnt > UIO_MAXIOV)
284: return (EINVAL);
285: MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
286: saveiov = iov;
287: } else
288: iov = aiov;
289: auio.uio_iov = iov;
290: auio.uio_iovcnt = uap->iovcnt;
291: auio.uio_rw = UIO_WRITE;
292: auio.uio_segflg = UIO_USERSPACE;
293: auio.uio_procp = p;
294: if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
295: goto done;
296: auio.uio_resid = 0;
297: for (i = 0; i < uap->iovcnt; i++) {
298: if (iov->iov_len < 0) {
299: error = EINVAL;
300: goto done;
301: }
302: auio.uio_resid += iov->iov_len;
303: if (auio.uio_resid < 0) {
304: error = EINVAL;
305: goto done;
306: }
307: iov++;
308: }
309: #ifdef KTRACE
310: /*
311: * if tracing, save a copy of iovec
312: */
313: if (KTRPOINT(p, KTR_GENIO)) {
314: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
315: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
316: }
317: #endif
318: cnt = auio.uio_resid;
319: if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
320: if (auio.uio_resid != cnt && (error == ERESTART ||
321: error == EINTR || error == EWOULDBLOCK))
322: error = 0;
323: if (error == EPIPE)
324: psignal(p, SIGPIPE);
325: }
326: cnt -= auio.uio_resid;
327: #ifdef KTRACE
328: if (ktriov != NULL) {
329: if (error == 0)
330: ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
331: ktriov, cnt, error);
332: FREE(ktriov, M_TEMP);
333: }
334: #endif
335: *retval = cnt;
336: done:
337: if (uap->iovcnt > UIO_SMALLIOV)
338: FREE(saveiov, M_IOV);
339: return (error);
340: }
341:
342: /*
343: * Ioctl system call
344: */
345: /* ARGSUSED */
346: ioctl(p, uap, retval)
347: struct proc *p;
348: register struct args {
349: int fdes;
350: int cmd;
351: caddr_t cmarg;
352: } *uap;
353: int *retval;
354: {
355: register struct file *fp;
356: register struct filedesc *fdp = p->p_fd;
357: register int com, error;
358: register u_int size;
359: caddr_t memp = 0;
360: #define STK_PARAMS 128
361: char stkbuf[STK_PARAMS];
362: caddr_t data = stkbuf;
363: int tmp;
364:
365: if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
366: (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
367: return (EBADF);
368: if ((fp->f_flag & (FREAD|FWRITE)) == 0)
369: return (EBADF);
370: com = uap->cmd;
371:
372: if (com == FIOCLEX) {
373: fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
374: return (0);
375: }
376: if (com == FIONCLEX) {
377: fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
378: return (0);
379: }
380:
381: /*
382: * Interpret high order word to find
383: * amount of data to be copied to/from the
384: * user's address space.
385: */
386: size = IOCPARM_LEN(com);
387: if (size > IOCPARM_MAX)
388: return (ENOTTY);
389: if (size > sizeof (stkbuf)) {
390: memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
391: data = memp;
392: }
393: if (com&IOC_IN) {
394: if (size) {
395: error = copyin(uap->cmarg, data, (u_int)size);
396: if (error) {
397: if (memp)
398: free(memp, M_IOCTLOPS);
399: return (error);
400: }
401: } else
402: *(caddr_t *)data = uap->cmarg;
403: } else if ((com&IOC_OUT) && size)
404: /*
405: * Zero the buffer so the user always
406: * gets back something deterministic.
407: */
408: bzero(data, size);
409: else if (com&IOC_VOID)
410: *(caddr_t *)data = uap->cmarg;
411:
412: switch (com) {
413:
414: case FIONBIO:
415: if (tmp = *(int *)data)
416: fp->f_flag |= FNONBLOCK;
417: else
418: fp->f_flag &= ~FNONBLOCK;
419: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
420: break;
421:
422: case FIOASYNC:
423: if (tmp = *(int *)data)
424: fp->f_flag |= FASYNC;
425: else
426: fp->f_flag &= ~FASYNC;
427: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
428: break;
429:
430: case FIOSETOWN:
431: tmp = *(int *)data;
432: if (fp->f_type == DTYPE_SOCKET) {
433: ((struct socket *)fp->f_data)->so_pgid = tmp;
434: error = 0;
435: break;
436: }
437: if (tmp <= 0) {
438: tmp = -tmp;
439: } else {
440: struct proc *p1 = pfind(tmp);
441: if (p1 == 0) {
442: error = ESRCH;
443: break;
444: }
445: tmp = p1->p_pgrp->pg_id;
446: }
447: error = (*fp->f_ops->fo_ioctl)
448: (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
449: break;
450:
451: case FIOGETOWN:
452: if (fp->f_type == DTYPE_SOCKET) {
453: error = 0;
454: *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
455: break;
456: }
457: error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
458: *(int *)data = -*(int *)data;
459: break;
460:
461: default:
462: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
463: /*
464: * Copy any data to user, size was
465: * already set and checked above.
466: */
467: if (error == 0 && (com&IOC_OUT) && size)
468: error = copyout(data, uap->cmarg, (u_int)size);
469: break;
470: }
471: if (memp)
472: free(memp, M_IOCTLOPS);
473: return (error);
474: }
475:
476: int selwait, nselcoll;
477:
478: /*
479: * Select system call.
480: */
481: select(p, uap, retval)
482: register struct proc *p;
483: register struct args {
484: int nd;
485: fd_set *in, *ou, *ex;
486: struct timeval *tv;
487: } *uap;
488: int *retval;
489: {
490: fd_set ibits[3], obits[3];
491: struct timeval atv;
492: int s, ncoll, ni, error = 0, timo;
493:
494: bzero((caddr_t)ibits, sizeof(ibits));
495: bzero((caddr_t)obits, sizeof(obits));
496: if (uap->nd > p->p_fd->fd_nfiles)
497: uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */
498: ni = howmany(uap->nd, NFDBITS);
499:
500: #define getbits(name, x) \
501: if (uap->name) { \
502: error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
503: (unsigned)(ni * sizeof(fd_mask))); \
504: if (error) \
505: goto done; \
506: }
507: getbits(in, 0);
508: getbits(ou, 1);
509: getbits(ex, 2);
510: #undef getbits
511:
512: if (uap->tv) {
513: error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
514: sizeof (atv));
515: if (error)
516: goto done;
517: if (itimerfix(&atv)) {
518: error = EINVAL;
519: goto done;
520: }
521: s = splhigh(); timevaladd(&atv, &time); splx(s);
522: timo = hzto(&atv);
523: } else
524: timo = 0;
525: retry:
526: ncoll = nselcoll;
527: p->p_flag |= SSEL;
528: error = selscan(p, ibits, obits, uap->nd, retval);
529: if (error || *retval)
530: goto done;
531: s = splhigh();
532: /* this should be timercmp(&time, &atv, >=) */
533: if (uap->tv && (time.tv_sec > atv.tv_sec ||
534: time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
535: splx(s);
536: goto done;
537: }
538: if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
539: splx(s);
540: goto retry;
541: }
542: p->p_flag &= ~SSEL;
543: error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
544: splx(s);
545: if (error == 0)
546: goto retry;
547: done:
548: p->p_flag &= ~SSEL;
549: /* select is not restarted after signals... */
550: if (error == ERESTART)
551: error = EINTR;
552: if (error == EWOULDBLOCK)
553: error = 0;
554: #define putbits(name, x) \
555: if (uap->name) { \
556: int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
557: (unsigned)(ni * sizeof(fd_mask))); \
558: if (error2) \
559: error = error2; \
560: }
561: if (error == 0) {
562: putbits(in, 0);
563: putbits(ou, 1);
564: putbits(ex, 2);
565: #undef putbits
566: }
567: return (error);
568: }
569:
570: selscan(p, ibits, obits, nfd, retval)
571: struct proc *p;
572: fd_set *ibits, *obits;
573: int nfd, *retval;
574: {
575: register struct filedesc *fdp = p->p_fd;
576: register int which, i, j;
577: register fd_mask bits;
578: int flag;
579: struct file *fp;
580: int error = 0, n = 0;
581:
582: for (which = 0; which < 3; which++) {
583: switch (which) {
584:
585: case 0:
586: flag = FREAD; break;
587:
588: case 1:
589: flag = FWRITE; break;
590:
591: case 2:
592: flag = 0; break;
593: }
594: for (i = 0; i < nfd; i += NFDBITS) {
595: bits = ibits[which].fds_bits[i/NFDBITS];
596: while ((j = ffs(bits)) && i + --j < nfd) {
597: bits &= ~(1 << j);
598: fp = fdp->fd_ofiles[i + j];
599: if (fp == NULL) {
600: error = EBADF;
601: break;
602: }
603: if ((*fp->f_ops->fo_select)(fp, flag, p)) {
604: FD_SET(i + j, &obits[which]);
605: n++;
606: }
607: }
608: }
609: }
610: *retval = n;
611: return (error);
612: }
613:
614: /*ARGSUSED*/
615: #ifdef __STDC__
616: seltrue(dev_t dev, int which, struct proc *p)
617: #else
618: seltrue(dev, flag, p)
619: dev_t dev;
620: int flag;
621: struct proc *p;
622: #endif
623: {
624:
625: return (1);
626: }
627:
628: selwakeup(p, coll)
629: register struct proc *p;
630: int coll;
631: {
632:
633: if (coll) {
634: nselcoll++;
635: wakeup((caddr_t)&selwait);
636: }
637: if (p) {
638: int s = splhigh();
639: if (p->p_wchan == (caddr_t)&selwait) {
640: if (p->p_stat == SSLEEP)
641: setrun(p);
642: else
643: unsleep(p);
644: } else if (p->p_flag & SSEL)
645: p->p_flag &= ~SSEL;
646: splx(s);
647: }
648: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.