Annotation of 43BSDReno/sys/kern/sys_generic.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.