The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/sys_generic.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: sys_generic.c,v 1.58 2007/09/07 15:00:20 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|M_ZERO);
  643                 pibits[0] = (fd_set *)&mbits[ni * 0];
  644                 pibits[1] = (fd_set *)&mbits[ni * 1];
  645                 pibits[2] = (fd_set *)&mbits[ni * 2];
  646                 pobits[0] = (fd_set *)&mbits[ni * 3];
  647                 pobits[1] = (fd_set *)&mbits[ni * 4];
  648                 pobits[2] = (fd_set *)&mbits[ni * 5];
  649         } else {
  650                 bzero(bits, sizeof(bits));
  651                 pibits[0] = (fd_set *)&bits[0];
  652                 pibits[1] = (fd_set *)&bits[1];
  653                 pibits[2] = (fd_set *)&bits[2];
  654                 pobits[0] = (fd_set *)&bits[3];
  655                 pobits[1] = (fd_set *)&bits[4];
  656                 pobits[2] = (fd_set *)&bits[5];
  657         }
  658 
  659 #define getbits(name, x) \
  660         if (SCARG(uap, name) && (error = copyin(SCARG(uap, name), \
  661             pibits[x], ni))) \
  662                 goto done;
  663         getbits(in, 0);
  664         getbits(ou, 1);
  665         getbits(ex, 2);
  666 #undef  getbits
  667 
  668         if (SCARG(uap, tv)) {
  669                 error = copyin(SCARG(uap, tv), &atv, sizeof (atv));
  670                 if (error)
  671                         goto done;
  672                 if (itimerfix(&atv)) {
  673                         error = EINVAL;
  674                         goto done;
  675                 }
  676                 getmicrouptime(&rtv);
  677                 timeradd(&atv, &rtv, &atv);
  678         } else {
  679                 atv.tv_sec = 0;
  680                 atv.tv_usec = 0;
  681         }
  682         timo = 0;
  683 
  684 retry:
  685         ncoll = nselcoll;
  686         atomic_setbits_int(&p->p_flag, P_SELECT);
  687         error = selscan(p, pibits[0], pobits[0], nd, ni, retval);
  688         if (error || *retval)
  689                 goto done;
  690         if (SCARG(uap, tv)) {
  691                 getmicrouptime(&rtv);
  692                 if (timercmp(&rtv, &atv, >=))
  693                         goto done;
  694                 ttv = atv;
  695                 timersub(&ttv, &rtv, &ttv);
  696                 timo = ttv.tv_sec > 24 * 60 * 60 ?
  697                         24 * 60 * 60 * hz : tvtohz(&ttv);
  698         }
  699         s = splhigh();
  700         if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
  701                 splx(s);
  702                 goto retry;
  703         }
  704         atomic_clearbits_int(&p->p_flag, P_SELECT);
  705         error = tsleep(&selwait, PSOCK | PCATCH, "select", timo);
  706         splx(s);
  707         if (error == 0)
  708                 goto retry;
  709 done:
  710         atomic_clearbits_int(&p->p_flag, P_SELECT);
  711         /* select is not restarted after signals... */
  712         if (error == ERESTART)
  713                 error = EINTR;
  714         if (error == EWOULDBLOCK)
  715                 error = 0;
  716 #define putbits(name, x) \
  717         if (SCARG(uap, name) && (error2 = copyout(pobits[x], \
  718             SCARG(uap, name), ni))) \
  719                 error = error2;
  720         if (error == 0) {
  721                 int error2;
  722 
  723                 putbits(in, 0);
  724                 putbits(ou, 1);
  725                 putbits(ex, 2);
  726 #undef putbits
  727         }
  728         
  729         if (pibits[0] != (fd_set *)&bits[0])
  730                 free(pibits[0], M_TEMP);
  731         return (error);
  732 }
  733 
  734 int
  735 selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int ni,
  736     register_t *retval)
  737 {
  738         caddr_t cibits = (caddr_t)ibits, cobits = (caddr_t)obits;
  739         struct filedesc *fdp = p->p_fd;
  740         int msk, i, j, fd;
  741         fd_mask bits;
  742         struct file *fp;
  743         int n = 0;
  744         static const int flag[3] = { POLLIN, POLLOUT, POLLPRI };
  745 
  746         for (msk = 0; msk < 3; msk++) {
  747                 fd_set *pibits = (fd_set *)&cibits[msk*ni];
  748                 fd_set *pobits = (fd_set *)&cobits[msk*ni];
  749 
  750                 for (i = 0; i < nfd; i += NFDBITS) {
  751                         bits = pibits->fds_bits[i/NFDBITS];
  752                         while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
  753                                 bits &= ~(1 << j);
  754                                 if ((fp = fd_getfile(fdp, fd)) == NULL)
  755                                         return (EBADF);
  756                                 FREF(fp);
  757                                 if ((*fp->f_ops->fo_poll)(fp, flag[msk], p)) {
  758                                         FD_SET(fd, pobits);
  759                                         n++;
  760                                 }
  761                                 FRELE(fp);
  762                         }
  763                 }
  764         }
  765         *retval = n;
  766         return (0);
  767 }
  768 
  769 /*ARGSUSED*/
  770 int
  771 seltrue(dev_t dev, int events, struct proc *p)
  772 {
  773 
  774         return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
  775 }
  776 
  777 /*
  778  * Record a select request.
  779  */
  780 void
  781 selrecord(struct proc *selector, struct selinfo *sip)
  782 {
  783         struct proc *p;
  784         pid_t mypid;
  785 
  786         mypid = selector->p_pid;
  787         if (sip->si_selpid == mypid)
  788                 return;
  789         if (sip->si_selpid && (p = pfind(sip->si_selpid)) &&
  790             p->p_wchan == (caddr_t)&selwait)
  791                 sip->si_flags |= SI_COLL;
  792         else
  793                 sip->si_selpid = mypid;
  794 }
  795 
  796 /*
  797  * Do a wakeup when a selectable event occurs.
  798  */
  799 void
  800 selwakeup(struct selinfo *sip)
  801 {
  802         struct proc *p;
  803         int s;
  804 
  805         if (sip->si_selpid == 0)
  806                 return;
  807         if (sip->si_flags & SI_COLL) {
  808                 nselcoll++;
  809                 sip->si_flags &= ~SI_COLL;
  810                 wakeup(&selwait);
  811         }
  812         p = pfind(sip->si_selpid);
  813         sip->si_selpid = 0;
  814         if (p != NULL) {
  815                 SCHED_LOCK(s);
  816                 if (p->p_wchan == (caddr_t)&selwait) {
  817                         if (p->p_stat == SSLEEP)
  818                                 setrunnable(p);
  819                         else
  820                                 unsleep(p);
  821                 } else if (p->p_flag & P_SELECT)
  822                         atomic_clearbits_int(&p->p_flag, P_SELECT);
  823                 SCHED_UNLOCK(s);
  824         }
  825 }
  826 
  827 void
  828 pollscan(struct proc *p, struct pollfd *pl, u_int nfd, register_t *retval)
  829 {
  830         struct filedesc *fdp = p->p_fd;
  831         struct file *fp;
  832         u_int i;
  833         int n = 0;
  834 
  835         for (i = 0; i < nfd; i++, pl++) {
  836                 /* Check the file descriptor. */
  837                 if (pl->fd < 0) {
  838                         pl->revents = 0;
  839                         continue;
  840                 }
  841                 if ((fp = fd_getfile(fdp, pl->fd)) == NULL) {
  842                         pl->revents = POLLNVAL;
  843                         n++;
  844                         continue;
  845                 }
  846                 FREF(fp);
  847                 pl->revents = (*fp->f_ops->fo_poll)(fp, pl->events, p);
  848                 FRELE(fp);
  849                 if (pl->revents != 0)
  850                         n++;
  851         }
  852         *retval = n;
  853 }
  854 
  855 /*
  856  * We are using the same mechanism as select only we encode/decode args
  857  * differently.
  858  */
  859 int
  860 sys_poll(struct proc *p, void *v, register_t *retval)
  861 {
  862         struct sys_poll_args /* {
  863                 syscallarg(struct pollfd *) fds;
  864                 syscallarg(u_int) nfds;
  865                 syscallarg(int) timeout;
  866         } */ *uap = v;
  867         size_t sz;
  868         struct pollfd pfds[4], *pl = pfds;
  869         int msec = SCARG(uap, timeout);
  870         struct timeval atv, rtv, ttv;
  871         int timo, ncoll, i, s, error;
  872         extern int nselcoll, selwait;
  873         u_int nfds = SCARG(uap, nfds);
  874 
  875         /* Standards say no more than MAX_OPEN; this is possibly better. */
  876         if (nfds > min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles))
  877                 return (EINVAL);
  878 
  879         sz = sizeof(struct pollfd) * nfds;
  880         
  881         /* optimize for the default case, of a small nfds value */
  882         if (sz > sizeof(pfds))
  883                 pl = (struct pollfd *) malloc(sz, M_TEMP, M_WAITOK);
  884 
  885         if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0)
  886                 goto bad;
  887 
  888         for (i = 0; i < nfds; i++)
  889                 pl[i].revents = 0;
  890 
  891         if (msec != INFTIM) {
  892                 atv.tv_sec = msec / 1000;
  893                 atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000;
  894 
  895                 if (itimerfix(&atv)) {
  896                         error = EINVAL;
  897                         goto done;
  898                 }
  899                 getmicrouptime(&rtv);
  900                 timeradd(&atv, &rtv, &atv);
  901         } else {
  902                 atv.tv_sec = 0;
  903                 atv.tv_usec = 0;
  904         }
  905         timo = 0;
  906 
  907 retry:
  908         ncoll = nselcoll;
  909         atomic_setbits_int(&p->p_flag, P_SELECT);
  910         pollscan(p, pl, nfds, retval);
  911         if (*retval)
  912                 goto done;
  913         if (msec != INFTIM) {
  914                 getmicrouptime(&rtv);
  915                 if (timercmp(&rtv, &atv, >=))
  916                         goto done;
  917                 ttv = atv;
  918                 timersub(&ttv, &rtv, &ttv);
  919                 timo = ttv.tv_sec > 24 * 60 * 60 ?
  920                         24 * 60 * 60 * hz : tvtohz(&ttv);
  921         }
  922         s = splhigh();
  923         if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
  924                 splx(s);
  925                 goto retry;
  926         }
  927         atomic_clearbits_int(&p->p_flag, P_SELECT);
  928         error = tsleep(&selwait, PSOCK | PCATCH, "poll", timo);
  929         splx(s);
  930         if (error == 0)
  931                 goto retry;
  932 
  933 done:
  934         atomic_clearbits_int(&p->p_flag, P_SELECT);
  935         /*
  936          * NOTE: poll(2) is not restarted after a signal and EWOULDBLOCK is
  937          *       ignored (since the whole point is to see what would block).
  938          */
  939         switch (error) {
  940         case ERESTART:
  941                 error = copyout(pl, SCARG(uap, fds), sz);
  942                 if (error == 0)
  943                         error = EINTR;
  944                 break;
  945         case EWOULDBLOCK:
  946         case 0:
  947                 error = copyout(pl, SCARG(uap, fds), sz);
  948                 break;
  949         }
  950 bad:
  951         if (pl != pfds)
  952                 free(pl, M_TEMP);
  953         return (error);
  954 }

Cache object: 6cc0325bc8e05a70bd70b9aeab258ff7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.