|
|
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.