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