[BACK]Return to sys_generic.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/sys_generic.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: sys_generic.c,v 1.57 2007/07/25 23:11:52 art Exp $    */
        !             2: /*     $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $     */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1996 Theo de Raadt
        !             6:  * Copyright (c) 1982, 1986, 1989, 1993
        !             7:  *     The Regents of the University of California.  All rights reserved.
        !             8:  * (c) UNIX System Laboratories, Inc.
        !             9:  * All or some portions of this file are derived from material licensed
        !            10:  * to the University of California by American Telephone and Telegraph
        !            11:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            12:  * the permission of UNIX System Laboratories, Inc.
        !            13:  *
        !            14:  * Redistribution and use in source and binary forms, with or without
        !            15:  * modification, are permitted provided that the following conditions
        !            16:  * are met:
        !            17:  * 1. Redistributions of source code must retain the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer.
        !            19:  * 2. Redistributions in binary form must reproduce the above copyright
        !            20:  *    notice, this list of conditions and the following disclaimer in the
        !            21:  *    documentation and/or other materials provided with the distribution.
        !            22:  * 3. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  *
        !            38:  *     @(#)sys_generic.c       8.5 (Berkeley) 1/21/94
        !            39:  */
        !            40:
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/filedesc.h>
        !            44: #include <sys/ioctl.h>
        !            45: #include <sys/file.h>
        !            46: #include <sys/proc.h>
        !            47: #include <sys/resourcevar.h>
        !            48: #include <sys/socketvar.h>
        !            49: #include <sys/signalvar.h>
        !            50: #include <sys/uio.h>
        !            51: #include <sys/kernel.h>
        !            52: #include <sys/stat.h>
        !            53: #include <sys/malloc.h>
        !            54: #include <sys/poll.h>
        !            55: #ifdef KTRACE
        !            56: #include <sys/ktrace.h>
        !            57: #endif
        !            58: #include <sys/sched.h>
        !            59:
        !            60: #include <sys/mount.h>
        !            61: #include <sys/syscallargs.h>
        !            62:
        !            63: #include <uvm/uvm_extern.h>
        !            64:
        !            65: int selscan(struct proc *, fd_set *, fd_set *, int, int, register_t *);
        !            66: int seltrue(dev_t, int, struct proc *);
        !            67: void pollscan(struct proc *, struct pollfd *, u_int, register_t *);
        !            68:
        !            69: /*
        !            70:  * Read system call.
        !            71:  */
        !            72: /* ARGSUSED */
        !            73: int
        !            74: sys_read(struct proc *p, void *v, register_t *retval)
        !            75: {
        !            76:        struct sys_read_args /* {
        !            77:                syscallarg(int) fd;
        !            78:                syscallarg(void *) buf;
        !            79:                syscallarg(size_t) nbyte;
        !            80:        } */ *uap = v;
        !            81:        int fd = SCARG(uap, fd);
        !            82:        struct file *fp;
        !            83:        struct filedesc *fdp = p->p_fd;
        !            84:
        !            85:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !            86:                return (EBADF);
        !            87:        if ((fp->f_flag & FREAD) == 0)
        !            88:                return (EBADF);
        !            89:
        !            90:        FREF(fp);
        !            91:
        !            92:        /* dofileread() will FRELE the descriptor for us */
        !            93:        return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
        !            94:            &fp->f_offset, retval));
        !            95: }
        !            96:
        !            97: int
        !            98: dofileread(struct proc *p, int fd, struct file *fp, void *buf, size_t nbyte,
        !            99:     off_t *offset, register_t *retval)
        !           100: {
        !           101:        struct uio auio;
        !           102:        struct iovec aiov;
        !           103:        long cnt, error = 0;
        !           104: #ifdef KTRACE
        !           105:        struct iovec ktriov;
        !           106: #endif
        !           107:
        !           108:        aiov.iov_base = buf;
        !           109:        aiov.iov_len = nbyte;
        !           110:        auio.uio_iov = &aiov;
        !           111:        auio.uio_iovcnt = 1;
        !           112:        auio.uio_resid = nbyte;
        !           113:        auio.uio_rw = UIO_READ;
        !           114:        auio.uio_segflg = UIO_USERSPACE;
        !           115:        auio.uio_procp = p;
        !           116:
        !           117:        /*
        !           118:         * Reads return ssize_t because -1 is returned on error.  Therefore
        !           119:         * we must restrict the length to SSIZE_MAX to avoid garbage return
        !           120:         * values.
        !           121:         */
        !           122:        if (auio.uio_resid > SSIZE_MAX) {
        !           123:                error = EINVAL;
        !           124:                goto out;
        !           125:        }
        !           126:
        !           127: #ifdef KTRACE
        !           128:        /*
        !           129:         * if tracing, save a copy of iovec
        !           130:         */
        !           131:        if (KTRPOINT(p, KTR_GENIO))
        !           132:                ktriov = aiov;
        !           133: #endif
        !           134:        cnt = auio.uio_resid;
        !           135:        error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred);
        !           136:        if (error)
        !           137:                if (auio.uio_resid != cnt && (error == ERESTART ||
        !           138:                    error == EINTR || error == EWOULDBLOCK))
        !           139:                        error = 0;
        !           140:        cnt -= auio.uio_resid;
        !           141:
        !           142:        fp->f_rxfer++;
        !           143:        fp->f_rbytes += cnt;
        !           144: #ifdef KTRACE
        !           145:        if (KTRPOINT(p, KTR_GENIO) && error == 0)
        !           146:                ktrgenio(p, fd, UIO_READ, &ktriov, cnt, error);
        !           147: #endif
        !           148:        *retval = cnt;
        !           149:  out:
        !           150:        FRELE(fp);
        !           151:        return (error);
        !           152: }
        !           153:
        !           154: /*
        !           155:  * Scatter read system call.
        !           156:  */
        !           157: int
        !           158: sys_readv(struct proc *p, void *v, register_t *retval)
        !           159: {
        !           160:        struct sys_readv_args /* {
        !           161:                syscallarg(int) fd;
        !           162:                syscallarg(const struct iovec *) iovp;
        !           163:                syscallarg(int) iovcnt;
        !           164:        } */ *uap = v;
        !           165:        int fd = SCARG(uap, fd);
        !           166:        struct file *fp;
        !           167:        struct filedesc *fdp = p->p_fd;
        !           168:
        !           169:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !           170:                return (EBADF);
        !           171:        if ((fp->f_flag & FREAD) == 0)
        !           172:                return (EBADF);
        !           173:
        !           174:        FREF(fp);
        !           175:
        !           176:        /* dofilereadv() will FRELE the descriptor for us */
        !           177:        return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
        !           178:            &fp->f_offset, retval));
        !           179: }
        !           180:
        !           181: int
        !           182: dofilereadv(struct proc *p, int fd, struct file *fp, const struct iovec *iovp,
        !           183:     int iovcnt, off_t *offset, register_t *retval)
        !           184: {
        !           185:        struct uio auio;
        !           186:        struct iovec *iov;
        !           187:        struct iovec *needfree;
        !           188:        struct iovec aiov[UIO_SMALLIOV];
        !           189:        long i, cnt, error = 0;
        !           190:        u_int iovlen;
        !           191: #ifdef KTRACE
        !           192:        struct iovec *ktriov = NULL;
        !           193: #endif
        !           194:
        !           195:        /* note: can't use iovlen until iovcnt is validated */
        !           196:        iovlen = iovcnt * sizeof(struct iovec);
        !           197:        if ((u_int)iovcnt > UIO_SMALLIOV) {
        !           198:                if ((u_int)iovcnt > IOV_MAX) {
        !           199:                        error = EINVAL;
        !           200:                        goto out;
        !           201:                }
        !           202:                iov = needfree = malloc(iovlen, M_IOV, M_WAITOK);
        !           203:        } else if ((u_int)iovcnt > 0) {
        !           204:                iov = aiov;
        !           205:                needfree = NULL;
        !           206:        } else {
        !           207:                error = EINVAL;
        !           208:                goto out;
        !           209:        }
        !           210:
        !           211:        auio.uio_iov = iov;
        !           212:        auio.uio_iovcnt = iovcnt;
        !           213:        auio.uio_rw = UIO_READ;
        !           214:        auio.uio_segflg = UIO_USERSPACE;
        !           215:        auio.uio_procp = p;
        !           216:        error = copyin(iovp, iov, iovlen);
        !           217:        if (error)
        !           218:                goto done;
        !           219:        auio.uio_resid = 0;
        !           220:        for (i = 0; i < iovcnt; i++) {
        !           221:                auio.uio_resid += iov->iov_len;
        !           222:                /*
        !           223:                 * Reads return ssize_t because -1 is returned on error.
        !           224:                 * Therefore we must restrict the length to SSIZE_MAX to
        !           225:                 * avoid garbage return values.
        !           226:                 */
        !           227:                if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
        !           228:                        error = EINVAL;
        !           229:                        goto done;
        !           230:                }
        !           231:                iov++;
        !           232:        }
        !           233: #ifdef KTRACE
        !           234:        /*
        !           235:         * if tracing, save a copy of iovec
        !           236:         */
        !           237:        if (KTRPOINT(p, KTR_GENIO))  {
        !           238:                ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
        !           239:                bcopy(auio.uio_iov, ktriov, iovlen);
        !           240:        }
        !           241: #endif
        !           242:        cnt = auio.uio_resid;
        !           243:        error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred);
        !           244:        if (error)
        !           245:                if (auio.uio_resid != cnt && (error == ERESTART ||
        !           246:                    error == EINTR || error == EWOULDBLOCK))
        !           247:                        error = 0;
        !           248:        cnt -= auio.uio_resid;
        !           249:
        !           250:        fp->f_rxfer++;
        !           251:        fp->f_rbytes += cnt;
        !           252: #ifdef KTRACE
        !           253:        if (ktriov != NULL) {
        !           254:                if (error == 0)
        !           255:                        ktrgenio(p, fd, UIO_READ, ktriov, cnt,
        !           256:                            error);
        !           257:                free(ktriov, M_TEMP);
        !           258:        }
        !           259: #endif
        !           260:        *retval = cnt;
        !           261:  done:
        !           262:        if (needfree)
        !           263:                free(needfree, M_IOV);
        !           264:  out:
        !           265:        FRELE(fp);
        !           266:        return (error);
        !           267: }
        !           268:
        !           269: /*
        !           270:  * Write system call
        !           271:  */
        !           272: int
        !           273: sys_write(struct proc *p, void *v, register_t *retval)
        !           274: {
        !           275:        struct sys_write_args /* {
        !           276:                syscallarg(int) fd;
        !           277:                syscallarg(const void *) buf;
        !           278:                syscallarg(size_t) nbyte;
        !           279:        } */ *uap = v;
        !           280:        int fd = SCARG(uap, fd);
        !           281:        struct file *fp;
        !           282:        struct filedesc *fdp = p->p_fd;
        !           283:
        !           284:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !           285:                return (EBADF);
        !           286:        if ((fp->f_flag & FWRITE) == 0)
        !           287:                return (EBADF);
        !           288:
        !           289:        FREF(fp);
        !           290:
        !           291:        /* dofilewrite() will FRELE the descriptor for us */
        !           292:        return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
        !           293:            &fp->f_offset, retval));
        !           294: }
        !           295:
        !           296: int
        !           297: dofilewrite(struct proc *p, int fd, struct file *fp, const void *buf,
        !           298:     size_t nbyte, off_t *offset, register_t *retval)
        !           299: {
        !           300:        struct uio auio;
        !           301:        struct iovec aiov;
        !           302:        long cnt, error = 0;
        !           303: #ifdef KTRACE
        !           304:        struct iovec ktriov;
        !           305: #endif
        !           306:
        !           307:        aiov.iov_base = (void *)buf;            /* XXX kills const */
        !           308:        aiov.iov_len = nbyte;
        !           309:        auio.uio_iov = &aiov;
        !           310:        auio.uio_iovcnt = 1;
        !           311:        auio.uio_resid = nbyte;
        !           312:        auio.uio_rw = UIO_WRITE;
        !           313:        auio.uio_segflg = UIO_USERSPACE;
        !           314:        auio.uio_procp = p;
        !           315:
        !           316:        /*
        !           317:         * Writes return ssize_t because -1 is returned on error.  Therefore
        !           318:         * we must restrict the length to SSIZE_MAX to avoid garbage return
        !           319:         * values.
        !           320:         */
        !           321:        if (auio.uio_resid > SSIZE_MAX) {
        !           322:                error = EINVAL;
        !           323:                goto out;
        !           324:        }
        !           325:
        !           326: #ifdef KTRACE
        !           327:        /*
        !           328:         * if tracing, save a copy of iovec
        !           329:         */
        !           330:        if (KTRPOINT(p, KTR_GENIO))
        !           331:                ktriov = aiov;
        !           332: #endif
        !           333:        cnt = auio.uio_resid;
        !           334:        error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred);
        !           335:        if (error) {
        !           336:                if (auio.uio_resid != cnt && (error == ERESTART ||
        !           337:                    error == EINTR || error == EWOULDBLOCK))
        !           338:                        error = 0;
        !           339:                if (error == EPIPE)
        !           340:                        psignal(p, SIGPIPE);
        !           341:        }
        !           342:        cnt -= auio.uio_resid;
        !           343:
        !           344:        fp->f_wxfer++;
        !           345:        fp->f_wbytes += cnt;
        !           346: #ifdef KTRACE
        !           347:        if (KTRPOINT(p, KTR_GENIO) && error == 0)
        !           348:                ktrgenio(p, fd, UIO_WRITE, &ktriov, cnt, error);
        !           349: #endif
        !           350:        *retval = cnt;
        !           351:  out:
        !           352:        FRELE(fp);
        !           353:        return (error);
        !           354: }
        !           355:
        !           356: /*
        !           357:  * Gather write system call
        !           358:  */
        !           359: int
        !           360: sys_writev(struct proc *p, void *v, register_t *retval)
        !           361: {
        !           362:        struct sys_writev_args /* {
        !           363:                syscallarg(int) fd;
        !           364:                syscallarg(const struct iovec *) iovp;
        !           365:                syscallarg(int) iovcnt;
        !           366:        } */ *uap = v;
        !           367:        int fd = SCARG(uap, fd);
        !           368:        struct file *fp;
        !           369:        struct filedesc *fdp = p->p_fd;
        !           370:
        !           371:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !           372:                return (EBADF);
        !           373:        if ((fp->f_flag & FWRITE) == 0)
        !           374:                return (EBADF);
        !           375:
        !           376:        FREF(fp);
        !           377:
        !           378:        /* dofilewritev() will FRELE the descriptor for us */
        !           379:        return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
        !           380:            &fp->f_offset, retval));
        !           381: }
        !           382:
        !           383: int
        !           384: dofilewritev(struct proc *p, int fd, struct file *fp, const struct iovec *iovp,
        !           385:     int iovcnt, off_t *offset, register_t *retval)
        !           386: {
        !           387:        struct uio auio;
        !           388:        struct iovec *iov;
        !           389:        struct iovec *needfree;
        !           390:        struct iovec aiov[UIO_SMALLIOV];
        !           391:        long i, cnt, error = 0;
        !           392:        u_int iovlen;
        !           393: #ifdef KTRACE
        !           394:        struct iovec *ktriov = NULL;
        !           395: #endif
        !           396:
        !           397:        /* note: can't use iovlen until iovcnt is validated */
        !           398:        iovlen = iovcnt * sizeof(struct iovec);
        !           399:        if ((u_int)iovcnt > UIO_SMALLIOV) {
        !           400:                if ((u_int)iovcnt > IOV_MAX) {
        !           401:                        error = EINVAL;
        !           402:                        goto out;
        !           403:                }
        !           404:                iov = needfree = malloc(iovlen, M_IOV, M_WAITOK);
        !           405:        } else if ((u_int)iovcnt > 0) {
        !           406:                iov = aiov;
        !           407:                needfree = NULL;
        !           408:        } else {
        !           409:                error = EINVAL;
        !           410:                goto out;
        !           411:        }
        !           412:
        !           413:        auio.uio_iov = iov;
        !           414:        auio.uio_iovcnt = iovcnt;
        !           415:        auio.uio_rw = UIO_WRITE;
        !           416:        auio.uio_segflg = UIO_USERSPACE;
        !           417:        auio.uio_procp = p;
        !           418:        error = copyin(iovp, iov, iovlen);
        !           419:        if (error)
        !           420:                goto done;
        !           421:        auio.uio_resid = 0;
        !           422:        for (i = 0; i < iovcnt; i++) {
        !           423:                auio.uio_resid += iov->iov_len;
        !           424:                /*
        !           425:                 * Writes return ssize_t because -1 is returned on error.
        !           426:                 * Therefore we must restrict the length to SSIZE_MAX to
        !           427:                 * avoid garbage return values.
        !           428:                 */
        !           429:                if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
        !           430:                        error = EINVAL;
        !           431:                        goto done;
        !           432:                }
        !           433:                iov++;
        !           434:        }
        !           435: #ifdef KTRACE
        !           436:        /*
        !           437:         * if tracing, save a copy of iovec
        !           438:         */
        !           439:        if (KTRPOINT(p, KTR_GENIO))  {
        !           440:                ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
        !           441:                bcopy(auio.uio_iov, ktriov, iovlen);
        !           442:        }
        !           443: #endif
        !           444:        cnt = auio.uio_resid;
        !           445:        error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred);
        !           446:        if (error) {
        !           447:                if (auio.uio_resid != cnt && (error == ERESTART ||
        !           448:                    error == EINTR || error == EWOULDBLOCK))
        !           449:                        error = 0;
        !           450:                if (error == EPIPE)
        !           451:                        psignal(p, SIGPIPE);
        !           452:        }
        !           453:        cnt -= auio.uio_resid;
        !           454:
        !           455:        fp->f_wxfer++;
        !           456:        fp->f_wbytes += cnt;
        !           457: #ifdef KTRACE
        !           458:        if (ktriov != NULL) {
        !           459:                if (error == 0)
        !           460:                        ktrgenio(p, fd, UIO_WRITE, ktriov, cnt, error);
        !           461:                free(ktriov, M_TEMP);
        !           462:        }
        !           463: #endif
        !           464:        *retval = cnt;
        !           465:  done:
        !           466:        if (needfree)
        !           467:                free(needfree, M_IOV);
        !           468:  out:
        !           469:        FRELE(fp);
        !           470:        return (error);
        !           471: }
        !           472:
        !           473: /*
        !           474:  * Ioctl system call
        !           475:  */
        !           476: /* ARGSUSED */
        !           477: int
        !           478: sys_ioctl(struct proc *p, void *v, register_t *retval)
        !           479: {
        !           480:        struct sys_ioctl_args /* {
        !           481:                syscallarg(int) fd;
        !           482:                syscallarg(u_long) com;
        !           483:                syscallarg(void *) data;
        !           484:        } */ *uap = v;
        !           485:        struct file *fp;
        !           486:        struct filedesc *fdp;
        !           487:        u_long com;
        !           488:        int error;
        !           489:        u_int size;
        !           490:        caddr_t data, memp;
        !           491:        int tmp;
        !           492: #define STK_PARAMS     128
        !           493:        char stkbuf[STK_PARAMS];
        !           494:
        !           495:        fdp = p->p_fd;
        !           496:        if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
        !           497:                return (EBADF);
        !           498:
        !           499:        if ((fp->f_flag & (FREAD | FWRITE)) == 0)
        !           500:                return (EBADF);
        !           501:
        !           502:        switch (com = SCARG(uap, com)) {
        !           503:        case FIONCLEX:
        !           504:                fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
        !           505:                return (0);
        !           506:        case FIOCLEX:
        !           507:                fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
        !           508:                return (0);
        !           509:        }
        !           510:
        !           511:        /*
        !           512:         * Interpret high order word to find amount of data to be
        !           513:         * copied to/from the user's address space.
        !           514:         */
        !           515:        size = IOCPARM_LEN(com);
        !           516:        if (size > IOCPARM_MAX)
        !           517:                return (ENOTTY);
        !           518:        FREF(fp);
        !           519:        memp = NULL;
        !           520:        if (size > sizeof (stkbuf)) {
        !           521:                memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
        !           522:                data = memp;
        !           523:        } else
        !           524:                data = stkbuf;
        !           525:        if (com&IOC_IN) {
        !           526:                if (size) {
        !           527:                        error = copyin(SCARG(uap, data), data, (u_int)size);
        !           528:                        if (error) {
        !           529:                                goto out;
        !           530:                        }
        !           531:                } else
        !           532:                        *(caddr_t *)data = SCARG(uap, data);
        !           533:        } else if ((com&IOC_OUT) && size)
        !           534:                /*
        !           535:                 * Zero the buffer so the user always
        !           536:                 * gets back something deterministic.
        !           537:                 */
        !           538:                bzero(data, size);
        !           539:        else if (com&IOC_VOID)
        !           540:                *(caddr_t *)data = SCARG(uap, data);
        !           541:
        !           542:        switch (com) {
        !           543:
        !           544:        case FIONBIO:
        !           545:                if ((tmp = *(int *)data) != 0)
        !           546:                        fp->f_flag |= FNONBLOCK;
        !           547:                else
        !           548:                        fp->f_flag &= ~FNONBLOCK;
        !           549:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
        !           550:                break;
        !           551:
        !           552:        case FIOASYNC:
        !           553:                if ((tmp = *(int *)data) != 0)
        !           554:                        fp->f_flag |= FASYNC;
        !           555:                else
        !           556:                        fp->f_flag &= ~FASYNC;
        !           557:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
        !           558:                break;
        !           559:
        !           560:        case FIOSETOWN:
        !           561:                tmp = *(int *)data;
        !           562:                if (fp->f_type == DTYPE_SOCKET) {
        !           563:                        struct socket *so = (struct socket *)fp->f_data;
        !           564:
        !           565:                        so->so_pgid = tmp;
        !           566:                        so->so_siguid = p->p_cred->p_ruid;
        !           567:                        so->so_sigeuid = p->p_ucred->cr_uid;
        !           568:                        error = 0;
        !           569:                        break;
        !           570:                }
        !           571:                if (tmp <= 0) {
        !           572:                        tmp = -tmp;
        !           573:                } else {
        !           574:                        struct proc *p1 = pfind(tmp);
        !           575:                        if (p1 == 0) {
        !           576:                                error = ESRCH;
        !           577:                                break;
        !           578:                        }
        !           579:                        tmp = p1->p_pgrp->pg_id;
        !           580:                }
        !           581:                error = (*fp->f_ops->fo_ioctl)
        !           582:                        (fp, TIOCSPGRP, (caddr_t)&tmp, p);
        !           583:                break;
        !           584:
        !           585:        case FIOGETOWN:
        !           586:                if (fp->f_type == DTYPE_SOCKET) {
        !           587:                        error = 0;
        !           588:                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
        !           589:                        break;
        !           590:                }
        !           591:                error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
        !           592:                *(int *)data = -*(int *)data;
        !           593:                break;
        !           594:
        !           595:        default:
        !           596:                error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
        !           597:                break;
        !           598:        }
        !           599:        /*
        !           600:         * Copy any data to user, size was
        !           601:         * already set and checked above.
        !           602:         */
        !           603:        if (error == 0 && (com&IOC_OUT) && size)
        !           604:                error = copyout(data, SCARG(uap, data), (u_int)size);
        !           605: out:
        !           606:        FRELE(fp);
        !           607:        if (memp)
        !           608:                free(memp, M_IOCTLOPS);
        !           609:        return (error);
        !           610: }
        !           611:
        !           612: int    selwait, nselcoll;
        !           613:
        !           614: /*
        !           615:  * Select system call.
        !           616:  */
        !           617: int
        !           618: sys_select(struct proc *p, void *v, register_t *retval)
        !           619: {
        !           620:        struct sys_select_args /* {
        !           621:                syscallarg(int) nd;
        !           622:                syscallarg(fd_set *) in;
        !           623:                syscallarg(fd_set *) ou;
        !           624:                syscallarg(fd_set *) ex;
        !           625:                syscallarg(struct timeval *) tv;
        !           626:        } */ *uap = v;
        !           627:        fd_mask bits[6];
        !           628:        fd_set *pibits[3], *pobits[3];
        !           629:        struct timeval atv, rtv, ttv;
        !           630:        int s, ncoll, error = 0, timo;
        !           631:        u_int nd, ni;
        !           632:
        !           633:        nd = SCARG(uap, nd);
        !           634:        if (nd > p->p_fd->fd_nfiles) {
        !           635:                /* forgiving; slightly wrong */
        !           636:                nd = p->p_fd->fd_nfiles;
        !           637:        }
        !           638:        ni = howmany(nd, NFDBITS) * sizeof(fd_mask);
        !           639:        if (nd > sizeof(bits[0])) {
        !           640:                caddr_t mbits;
        !           641:
        !           642:                mbits = malloc(ni * 6, M_TEMP, M_WAITOK);
        !           643:                bzero(mbits, ni * 6);
        !           644:                pibits[0] = (fd_set *)&mbits[ni * 0];
        !           645:                pibits[1] = (fd_set *)&mbits[ni * 1];
        !           646:                pibits[2] = (fd_set *)&mbits[ni * 2];
        !           647:                pobits[0] = (fd_set *)&mbits[ni * 3];
        !           648:                pobits[1] = (fd_set *)&mbits[ni * 4];
        !           649:                pobits[2] = (fd_set *)&mbits[ni * 5];
        !           650:        } else {
        !           651:                bzero(bits, sizeof(bits));
        !           652:                pibits[0] = (fd_set *)&bits[0];
        !           653:                pibits[1] = (fd_set *)&bits[1];
        !           654:                pibits[2] = (fd_set *)&bits[2];
        !           655:                pobits[0] = (fd_set *)&bits[3];
        !           656:                pobits[1] = (fd_set *)&bits[4];
        !           657:                pobits[2] = (fd_set *)&bits[5];
        !           658:        }
        !           659:
        !           660: #define        getbits(name, x) \
        !           661:        if (SCARG(uap, name) && (error = copyin(SCARG(uap, name), \
        !           662:            pibits[x], ni))) \
        !           663:                goto done;
        !           664:        getbits(in, 0);
        !           665:        getbits(ou, 1);
        !           666:        getbits(ex, 2);
        !           667: #undef getbits
        !           668:
        !           669:        if (SCARG(uap, tv)) {
        !           670:                error = copyin(SCARG(uap, tv), &atv, sizeof (atv));
        !           671:                if (error)
        !           672:                        goto done;
        !           673:                if (itimerfix(&atv)) {
        !           674:                        error = EINVAL;
        !           675:                        goto done;
        !           676:                }
        !           677:                getmicrouptime(&rtv);
        !           678:                timeradd(&atv, &rtv, &atv);
        !           679:        } else {
        !           680:                atv.tv_sec = 0;
        !           681:                atv.tv_usec = 0;
        !           682:        }
        !           683:        timo = 0;
        !           684:
        !           685: retry:
        !           686:        ncoll = nselcoll;
        !           687:        atomic_setbits_int(&p->p_flag, P_SELECT);
        !           688:        error = selscan(p, pibits[0], pobits[0], nd, ni, retval);
        !           689:        if (error || *retval)
        !           690:                goto done;
        !           691:        if (SCARG(uap, tv)) {
        !           692:                getmicrouptime(&rtv);
        !           693:                if (timercmp(&rtv, &atv, >=))
        !           694:                        goto done;
        !           695:                ttv = atv;
        !           696:                timersub(&ttv, &rtv, &ttv);
        !           697:                timo = ttv.tv_sec > 24 * 60 * 60 ?
        !           698:                        24 * 60 * 60 * hz : tvtohz(&ttv);
        !           699:        }
        !           700:        s = splhigh();
        !           701:        if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
        !           702:                splx(s);
        !           703:                goto retry;
        !           704:        }
        !           705:        atomic_clearbits_int(&p->p_flag, P_SELECT);
        !           706:        error = tsleep(&selwait, PSOCK | PCATCH, "select", timo);
        !           707:        splx(s);
        !           708:        if (error == 0)
        !           709:                goto retry;
        !           710: done:
        !           711:        atomic_clearbits_int(&p->p_flag, P_SELECT);
        !           712:        /* select is not restarted after signals... */
        !           713:        if (error == ERESTART)
        !           714:                error = EINTR;
        !           715:        if (error == EWOULDBLOCK)
        !           716:                error = 0;
        !           717: #define        putbits(name, x) \
        !           718:        if (SCARG(uap, name) && (error2 = copyout(pobits[x], \
        !           719:            SCARG(uap, name), ni))) \
        !           720:                error = error2;
        !           721:        if (error == 0) {
        !           722:                int error2;
        !           723:
        !           724:                putbits(in, 0);
        !           725:                putbits(ou, 1);
        !           726:                putbits(ex, 2);
        !           727: #undef putbits
        !           728:        }
        !           729:
        !           730:        if (pibits[0] != (fd_set *)&bits[0])
        !           731:                free(pibits[0], M_TEMP);
        !           732:        return (error);
        !           733: }
        !           734:
        !           735: int
        !           736: selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int ni,
        !           737:     register_t *retval)
        !           738: {
        !           739:        caddr_t cibits = (caddr_t)ibits, cobits = (caddr_t)obits;
        !           740:        struct filedesc *fdp = p->p_fd;
        !           741:        int msk, i, j, fd;
        !           742:        fd_mask bits;
        !           743:        struct file *fp;
        !           744:        int n = 0;
        !           745:        static const int flag[3] = { POLLIN, POLLOUT, POLLPRI };
        !           746:
        !           747:        for (msk = 0; msk < 3; msk++) {
        !           748:                fd_set *pibits = (fd_set *)&cibits[msk*ni];
        !           749:                fd_set *pobits = (fd_set *)&cobits[msk*ni];
        !           750:
        !           751:                for (i = 0; i < nfd; i += NFDBITS) {
        !           752:                        bits = pibits->fds_bits[i/NFDBITS];
        !           753:                        while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
        !           754:                                bits &= ~(1 << j);
        !           755:                                if ((fp = fd_getfile(fdp, fd)) == NULL)
        !           756:                                        return (EBADF);
        !           757:                                FREF(fp);
        !           758:                                if ((*fp->f_ops->fo_poll)(fp, flag[msk], p)) {
        !           759:                                        FD_SET(fd, pobits);
        !           760:                                        n++;
        !           761:                                }
        !           762:                                FRELE(fp);
        !           763:                        }
        !           764:                }
        !           765:        }
        !           766:        *retval = n;
        !           767:        return (0);
        !           768: }
        !           769:
        !           770: /*ARGSUSED*/
        !           771: int
        !           772: seltrue(dev_t dev, int events, struct proc *p)
        !           773: {
        !           774:
        !           775:        return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
        !           776: }
        !           777:
        !           778: /*
        !           779:  * Record a select request.
        !           780:  */
        !           781: void
        !           782: selrecord(struct proc *selector, struct selinfo *sip)
        !           783: {
        !           784:        struct proc *p;
        !           785:        pid_t mypid;
        !           786:
        !           787:        mypid = selector->p_pid;
        !           788:        if (sip->si_selpid == mypid)
        !           789:                return;
        !           790:        if (sip->si_selpid && (p = pfind(sip->si_selpid)) &&
        !           791:            p->p_wchan == (caddr_t)&selwait)
        !           792:                sip->si_flags |= SI_COLL;
        !           793:        else
        !           794:                sip->si_selpid = mypid;
        !           795: }
        !           796:
        !           797: /*
        !           798:  * Do a wakeup when a selectable event occurs.
        !           799:  */
        !           800: void
        !           801: selwakeup(struct selinfo *sip)
        !           802: {
        !           803:        struct proc *p;
        !           804:        int s;
        !           805:
        !           806:        if (sip->si_selpid == 0)
        !           807:                return;
        !           808:        if (sip->si_flags & SI_COLL) {
        !           809:                nselcoll++;
        !           810:                sip->si_flags &= ~SI_COLL;
        !           811:                wakeup(&selwait);
        !           812:        }
        !           813:        p = pfind(sip->si_selpid);
        !           814:        sip->si_selpid = 0;
        !           815:        if (p != NULL) {
        !           816:                SCHED_LOCK(s);
        !           817:                if (p->p_wchan == (caddr_t)&selwait) {
        !           818:                        if (p->p_stat == SSLEEP)
        !           819:                                setrunnable(p);
        !           820:                        else
        !           821:                                unsleep(p);
        !           822:                } else if (p->p_flag & P_SELECT)
        !           823:                        atomic_clearbits_int(&p->p_flag, P_SELECT);
        !           824:                SCHED_UNLOCK(s);
        !           825:        }
        !           826: }
        !           827:
        !           828: void
        !           829: pollscan(struct proc *p, struct pollfd *pl, u_int nfd, register_t *retval)
        !           830: {
        !           831:        struct filedesc *fdp = p->p_fd;
        !           832:        struct file *fp;
        !           833:        u_int i;
        !           834:        int n = 0;
        !           835:
        !           836:        for (i = 0; i < nfd; i++, pl++) {
        !           837:                /* Check the file descriptor. */
        !           838:                if (pl->fd < 0) {
        !           839:                        pl->revents = 0;
        !           840:                        continue;
        !           841:                }
        !           842:                if ((fp = fd_getfile(fdp, pl->fd)) == NULL) {
        !           843:                        pl->revents = POLLNVAL;
        !           844:                        n++;
        !           845:                        continue;
        !           846:                }
        !           847:                FREF(fp);
        !           848:                pl->revents = (*fp->f_ops->fo_poll)(fp, pl->events, p);
        !           849:                FRELE(fp);
        !           850:                if (pl->revents != 0)
        !           851:                        n++;
        !           852:        }
        !           853:        *retval = n;
        !           854: }
        !           855:
        !           856: /*
        !           857:  * We are using the same mechanism as select only we encode/decode args
        !           858:  * differently.
        !           859:  */
        !           860: int
        !           861: sys_poll(struct proc *p, void *v, register_t *retval)
        !           862: {
        !           863:        struct sys_poll_args /* {
        !           864:                syscallarg(struct pollfd *) fds;
        !           865:                syscallarg(u_int) nfds;
        !           866:                syscallarg(int) timeout;
        !           867:        } */ *uap = v;
        !           868:        size_t sz;
        !           869:        struct pollfd pfds[4], *pl = pfds;
        !           870:        int msec = SCARG(uap, timeout);
        !           871:        struct timeval atv, rtv, ttv;
        !           872:        int timo, ncoll, i, s, error;
        !           873:        extern int nselcoll, selwait;
        !           874:        u_int nfds = SCARG(uap, nfds);
        !           875:
        !           876:        /* Standards say no more than MAX_OPEN; this is possibly better. */
        !           877:        if (nfds > min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles))
        !           878:                return (EINVAL);
        !           879:
        !           880:        sz = sizeof(struct pollfd) * nfds;
        !           881:
        !           882:        /* optimize for the default case, of a small nfds value */
        !           883:        if (sz > sizeof(pfds))
        !           884:                pl = (struct pollfd *) malloc(sz, M_TEMP, M_WAITOK);
        !           885:
        !           886:        if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0)
        !           887:                goto bad;
        !           888:
        !           889:        for (i = 0; i < nfds; i++)
        !           890:                pl[i].revents = 0;
        !           891:
        !           892:        if (msec != INFTIM) {
        !           893:                atv.tv_sec = msec / 1000;
        !           894:                atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000;
        !           895:
        !           896:                if (itimerfix(&atv)) {
        !           897:                        error = EINVAL;
        !           898:                        goto done;
        !           899:                }
        !           900:                getmicrouptime(&rtv);
        !           901:                timeradd(&atv, &rtv, &atv);
        !           902:        } else {
        !           903:                atv.tv_sec = 0;
        !           904:                atv.tv_usec = 0;
        !           905:        }
        !           906:        timo = 0;
        !           907:
        !           908: retry:
        !           909:        ncoll = nselcoll;
        !           910:        atomic_setbits_int(&p->p_flag, P_SELECT);
        !           911:        pollscan(p, pl, nfds, retval);
        !           912:        if (*retval)
        !           913:                goto done;
        !           914:        if (msec != INFTIM) {
        !           915:                getmicrouptime(&rtv);
        !           916:                if (timercmp(&rtv, &atv, >=))
        !           917:                        goto done;
        !           918:                ttv = atv;
        !           919:                timersub(&ttv, &rtv, &ttv);
        !           920:                timo = ttv.tv_sec > 24 * 60 * 60 ?
        !           921:                        24 * 60 * 60 * hz : tvtohz(&ttv);
        !           922:        }
        !           923:        s = splhigh();
        !           924:        if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
        !           925:                splx(s);
        !           926:                goto retry;
        !           927:        }
        !           928:        atomic_clearbits_int(&p->p_flag, P_SELECT);
        !           929:        error = tsleep(&selwait, PSOCK | PCATCH, "poll", timo);
        !           930:        splx(s);
        !           931:        if (error == 0)
        !           932:                goto retry;
        !           933:
        !           934: done:
        !           935:        atomic_clearbits_int(&p->p_flag, P_SELECT);
        !           936:        /*
        !           937:         * NOTE: poll(2) is not restarted after a signal and EWOULDBLOCK is
        !           938:         *       ignored (since the whole point is to see what would block).
        !           939:         */
        !           940:        switch (error) {
        !           941:        case ERESTART:
        !           942:                error = copyout(pl, SCARG(uap, fds), sz);
        !           943:                if (error == 0)
        !           944:                        error = EINTR;
        !           945:                break;
        !           946:        case EWOULDBLOCK:
        !           947:        case 0:
        !           948:                error = copyout(pl, SCARG(uap, fds), sz);
        !           949:                break;
        !           950:        }
        !           951: bad:
        !           952:        if (pl != pfds)
        !           953:                free(pl, M_TEMP);
        !           954:        return (error);
        !           955: }

CVSweb