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/kern_descrip.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1989, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. 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  *      @(#)kern_descrip.c      8.6 (Berkeley) 4/19/94
   39  * $FreeBSD: src/sys/kern/kern_descrip.c,v 1.32.2.4 2000/01/25 18:09:08 dillon Exp $
   40  */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/sysproto.h>
   45 #include <sys/conf.h>
   46 #include <sys/filedesc.h>
   47 #include <sys/kernel.h>
   48 #include <sys/sysctl.h>
   49 #include <sys/vnode.h>
   50 #include <sys/proc.h>
   51 #include <sys/file.h>
   52 #include <sys/socketvar.h>
   53 #include <sys/stat.h>
   54 #include <sys/filio.h>
   55 #include <sys/ttycom.h>
   56 #include <sys/fcntl.h>
   57 #include <sys/malloc.h>
   58 #include <sys/unistd.h>
   59 #include <sys/resourcevar.h>
   60 #include <sys/pipe.h>
   61 
   62 #include <vm/vm.h>
   63 #include <vm/vm_extern.h>
   64 
   65 #ifdef DEVFS
   66 #include <sys/devfsext.h>
   67 #endif /*DEVFS*/
   68 
   69 static   d_open_t  fdopen;
   70 #define NUMFDESC 64
   71 
   72 #define CDEV_MAJOR 22
   73 static struct cdevsw fildesc_cdevsw = 
   74         { fdopen,       noclose,        noread,         nowrite,        /*22*/
   75           noioc,        nostop,         nullreset,      nodevtotty,/*fd(!=Fd)*/
   76           noselect,     nommap,         nostrat };
   77 
   78 static int finishdup(struct filedesc *fdp, int old, int new, int *retval);
   79 /*
   80  * Descriptor management.
   81  */
   82 struct filelist filehead;       /* head of list of open files */
   83 int nfiles;                     /* actual number of open files */
   84 extern int cmask;       
   85 
   86 /*
   87  * System calls on descriptors.
   88  */
   89 #ifndef _SYS_SYSPROTO_H_
   90 struct getdtablesize_args {
   91         int     dummy;
   92 };
   93 #endif
   94 /* ARGSUSED */
   95 int
   96 getdtablesize(p, uap, retval)
   97         struct proc *p;
   98         struct getdtablesize_args *uap;
   99         int *retval;
  100 {
  101 
  102         *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
  103         return (0);
  104 }
  105 
  106 /*
  107  * Duplicate a file descriptor to a particular value.
  108  */
  109 #ifndef _SYS_SYSPROTO_H_
  110 struct dup2_args {
  111         u_int   from;
  112         u_int   to;
  113 };
  114 #endif
  115 /* ARGSUSED */
  116 int
  117 dup2(p, uap, retval)
  118         struct proc *p;
  119         struct dup2_args *uap;
  120         int *retval;
  121 {
  122         register struct filedesc *fdp = p->p_fd;
  123         register u_int old = uap->from, new = uap->to;
  124         int i, error;
  125 
  126         if (old >= fdp->fd_nfiles ||
  127             fdp->fd_ofiles[old] == NULL ||
  128             new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  129             new >= maxfilesperproc)
  130                 return (EBADF);
  131         if (old == new) {
  132                 *retval = new;
  133                 return (0);
  134         }
  135         if (new >= fdp->fd_nfiles) {
  136                 if ((error = fdalloc(p, new, &i)))
  137                         return (error);
  138                 if (new != i)
  139                         panic("dup2: fdalloc");
  140         } else if (fdp->fd_ofiles[new]) {
  141                 if (fdp->fd_ofileflags[new] & UF_MAPPED)
  142                         (void) munmapfd(p, new);
  143                 /*
  144                  * dup2() must succeed even if the close has an error.
  145                  */
  146                 (void) closef(fdp->fd_ofiles[new], p);
  147         }
  148         return (finishdup(fdp, (int)old, (int)new, retval));
  149 }
  150 
  151 /*
  152  * Duplicate a file descriptor.
  153  */
  154 #ifndef _SYS_SYSPROTO_H_
  155 struct dup_args {
  156         u_int   fd;
  157 };
  158 #endif
  159 /* ARGSUSED */
  160 int
  161 dup(p, uap, retval)
  162         struct proc *p;
  163         struct dup_args *uap;
  164         int *retval;
  165 {
  166         register struct filedesc *fdp;
  167         u_int old;
  168         int new, error;
  169 
  170         old = uap->fd;
  171 
  172 #if 0
  173         /*
  174          * XXX Compatibility
  175          */
  176         if (old &~ 077) { uap->fd &= 077; return (dup2(p, uap, retval)); }
  177 #endif
  178 
  179         fdp = p->p_fd;
  180         if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL)
  181                 return (EBADF);
  182         if ((error = fdalloc(p, 0, &new)))
  183                 return (error);
  184         return (finishdup(fdp, (int)old, new, retval));
  185 }
  186 
  187 /*
  188  * The file control system call.
  189  */
  190 #ifndef _SYS_SYSPROTO_H_
  191 struct fcntl_args {
  192         int     fd;
  193         int     cmd;
  194         int     arg;
  195 };
  196 #endif
  197 /* ARGSUSED */
  198 int
  199 fcntl(p, uap, retval)
  200         struct proc *p;
  201         register struct fcntl_args *uap;
  202         int *retval;
  203 {
  204         register struct filedesc *fdp = p->p_fd;
  205         register struct file *fp;
  206         register char *pop;
  207         struct vnode *vp;
  208         int i, tmp, error, flg = F_POSIX;
  209         struct flock fl;
  210         u_int newmin;
  211 
  212         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  213             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  214                 return (EBADF);
  215         pop = &fdp->fd_ofileflags[uap->fd];
  216         switch (uap->cmd) {
  217 
  218         case F_DUPFD:
  219                 newmin = uap->arg;
  220                 if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  221                     newmin >= maxfilesperproc)
  222                         return (EINVAL);
  223                 if ((error = fdalloc(p, newmin, &i)))
  224                         return (error);
  225                 return (finishdup(fdp, uap->fd, i, retval));
  226 
  227         case F_GETFD:
  228                 *retval = *pop & 1;
  229                 return (0);
  230 
  231         case F_SETFD:
  232                 *pop = (*pop &~ 1) | (uap->arg & 1);
  233                 return (0);
  234 
  235         case F_GETFL:
  236                 *retval = OFLAGS(fp->f_flag);
  237                 return (0);
  238 
  239         case F_SETFL:
  240                 fp->f_flag &= ~FCNTLFLAGS;
  241                 fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
  242                 tmp = fp->f_flag & FNONBLOCK;
  243                 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  244                 if (error)
  245                         return (error);
  246                 tmp = fp->f_flag & FASYNC;
  247                 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
  248                 if (!error)
  249                         return (0);
  250                 fp->f_flag &= ~FNONBLOCK;
  251                 tmp = 0;
  252                 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  253                 return (error);
  254 
  255         case F_GETOWN:
  256                 if (fp->f_type == DTYPE_SOCKET) {
  257                         *retval = ((struct socket *)fp->f_data)->so_pgid;
  258                         return (0);
  259                 }
  260                 error = (*fp->f_ops->fo_ioctl)
  261                         (fp, TIOCGPGRP, (caddr_t)retval, p);
  262                 *retval = -*retval;
  263                 return (error);
  264 
  265         case F_SETOWN:
  266                 if (fp->f_type == DTYPE_SOCKET) {
  267                         ((struct socket *)fp->f_data)->so_pgid = uap->arg;
  268                         return (0);
  269                 }
  270                 if (uap->arg <= 0) {
  271                         uap->arg = -uap->arg;
  272                 } else {
  273                         struct proc *p1 = pfind(uap->arg);
  274                         if (p1 == 0)
  275                                 return (ESRCH);
  276                         uap->arg = p1->p_pgrp->pg_id;
  277                 }
  278                 return ((*fp->f_ops->fo_ioctl)
  279                         (fp, TIOCSPGRP, (caddr_t)&uap->arg, p));
  280 
  281         case F_SETLKW:
  282                 flg |= F_WAIT;
  283                 /* Fall into F_SETLK */
  284 
  285         case F_SETLK:
  286                 if (fp->f_type != DTYPE_VNODE)
  287                         return (EBADF);
  288                 vp = (struct vnode *)fp->f_data;
  289                 /* Copy in the lock structure */
  290                 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
  291                 if (error)
  292                         return (error);
  293                 if (fl.l_whence == SEEK_CUR)
  294                         fl.l_start += fp->f_offset;
  295                 switch (fl.l_type) {
  296 
  297                 case F_RDLCK:
  298                         if ((fp->f_flag & FREAD) == 0)
  299                                 return (EBADF);
  300                         p->p_flag |= P_ADVLOCK;
  301                         return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  302 
  303                 case F_WRLCK:
  304                         if ((fp->f_flag & FWRITE) == 0)
  305                                 return (EBADF);
  306                         p->p_flag |= P_ADVLOCK;
  307                         return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  308 
  309                 case F_UNLCK:
  310                         return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
  311                                 F_POSIX));
  312 
  313                 default:
  314                         return (EINVAL);
  315                 }
  316 
  317         case F_GETLK:
  318                 if (fp->f_type != DTYPE_VNODE)
  319                         return (EBADF);
  320                 vp = (struct vnode *)fp->f_data;
  321                 /* Copy in the lock structure */
  322                 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
  323                 if (error)
  324                         return (error);
  325                 if (fl.l_type != F_RDLCK && fl.l_type != F_WRLCK &&
  326                     fl.l_type != F_UNLCK)
  327                         return (EINVAL);
  328                 if (fl.l_whence == SEEK_CUR)
  329                         fl.l_start += fp->f_offset;
  330                 if ((error = VOP_ADVLOCK(vp,(caddr_t)p,F_GETLK,&fl,F_POSIX)))
  331                         return (error);
  332                 return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
  333 
  334         default:
  335                 return (EINVAL);
  336         }
  337         /* NOTREACHED */
  338 }
  339 
  340 /*
  341  * Common code for dup, dup2, and fcntl(F_DUPFD).
  342  */
  343 static int
  344 finishdup(fdp, old, new, retval)
  345         register struct filedesc *fdp;
  346         register int old, new, *retval;
  347 {
  348         register struct file *fp;
  349 
  350         fp = fdp->fd_ofiles[old];
  351         fdp->fd_ofiles[new] = fp;
  352         fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
  353         fp->f_count++;
  354         if (new > fdp->fd_lastfile)
  355                 fdp->fd_lastfile = new;
  356         *retval = new;
  357         return (0);
  358 }
  359 
  360 /*
  361  * Close a file descriptor.
  362  */
  363 #ifndef _SYS_SYSPROTO_H_
  364 struct close_args {
  365         int     fd;
  366 };
  367 #endif
  368 /* ARGSUSED */
  369 int
  370 close(p, uap, retval)
  371         struct proc *p;
  372         struct close_args *uap;
  373         int *retval;
  374 {
  375         register struct filedesc *fdp = p->p_fd;
  376         register struct file *fp;
  377         register int fd = uap->fd;
  378         register u_char *pf;
  379 
  380         if ((unsigned)fd >= fdp->fd_nfiles ||
  381             (fp = fdp->fd_ofiles[fd]) == NULL)
  382                 return (EBADF);
  383         pf = (u_char *)&fdp->fd_ofileflags[fd];
  384         if (*pf & UF_MAPPED)
  385                 (void) munmapfd(p, fd);
  386         fdp->fd_ofiles[fd] = NULL;
  387         while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
  388                 fdp->fd_lastfile--;
  389         if (fd < fdp->fd_freefile)
  390                 fdp->fd_freefile = fd;
  391         *pf = 0;
  392         return (closef(fp, p));
  393 }
  394 
  395 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  396 /*
  397  * Return status information about a file descriptor.
  398  */
  399 #ifndef _SYS_SYSPROTO_H_
  400 struct ofstat_args {
  401         int     fd;
  402         struct  ostat *sb;
  403 };
  404 #endif
  405 /* ARGSUSED */
  406 int
  407 ofstat(p, uap, retval)
  408         struct proc *p;
  409         register struct ofstat_args *uap;
  410         int *retval;
  411 {
  412         register struct filedesc *fdp = p->p_fd;
  413         register struct file *fp;
  414         struct stat ub;
  415         struct ostat oub;
  416         int error;
  417 
  418         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  419             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  420                 return (EBADF);
  421         switch (fp->f_type) {
  422 
  423         case DTYPE_FIFO:
  424         case DTYPE_VNODE:
  425                 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
  426                 break;
  427 
  428         case DTYPE_SOCKET:
  429                 error = soo_stat((struct socket *)fp->f_data, &ub);
  430                 break;
  431 
  432 #ifndef OLD_PIPE
  433         case DTYPE_PIPE:
  434                 error = pipe_stat((struct pipe *)fp->f_data, &ub);
  435                 break;
  436 #endif
  437 
  438         default:
  439                 panic("ofstat");
  440                 /*NOTREACHED*/
  441         }
  442         cvtstat(&ub, &oub);
  443         if (error == 0)
  444                 error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub));
  445         return (error);
  446 }
  447 #endif /* COMPAT_43 || COMPAT_SUNOS */
  448 
  449 /*
  450  * Return status information about a file descriptor.
  451  */
  452 #ifndef _SYS_SYSPROTO_H_
  453 struct fstat_args {
  454         int     fd;
  455         struct  stat *sb;
  456 };
  457 #endif
  458 /* ARGSUSED */
  459 int
  460 fstat(p, uap, retval)
  461         struct proc *p;
  462         register struct fstat_args *uap;
  463         int *retval;
  464 {
  465         register struct filedesc *fdp = p->p_fd;
  466         register struct file *fp;
  467         struct stat ub;
  468         int error;
  469 
  470         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  471             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  472                 return (EBADF);
  473         switch (fp->f_type) {
  474 
  475         case DTYPE_FIFO:
  476         case DTYPE_VNODE:
  477                 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
  478                 break;
  479 
  480         case DTYPE_SOCKET:
  481                 error = soo_stat((struct socket *)fp->f_data, &ub);
  482                 break;
  483 
  484 #ifndef OLD_PIPE
  485         case DTYPE_PIPE:
  486                 error = pipe_stat((struct pipe *)fp->f_data, &ub);
  487                 break;
  488 #endif
  489 
  490         default:
  491                 panic("fstat");
  492                 /*NOTREACHED*/
  493         }
  494         if (error == 0)
  495                 error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
  496         return (error);
  497 }
  498 
  499 /*
  500  * Return pathconf information about a file descriptor.
  501  */
  502 #ifndef _SYS_SYSPROTO_H_
  503 struct fpathconf_args {
  504         int     fd;
  505         int     name;
  506 };
  507 #endif
  508 /* ARGSUSED */
  509 int
  510 fpathconf(p, uap, retval)
  511         struct proc *p;
  512         register struct fpathconf_args *uap;
  513         int *retval;
  514 {
  515         struct filedesc *fdp = p->p_fd;
  516         struct file *fp;
  517         struct vnode *vp;
  518 
  519         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  520             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  521                 return (EBADF);
  522         switch (fp->f_type) {
  523 
  524 #ifndef OLD_PIPE
  525         case DTYPE_PIPE:
  526 #endif
  527         case DTYPE_SOCKET:
  528                 if (uap->name != _PC_PIPE_BUF)
  529                         return (EINVAL);
  530                 *retval = PIPE_BUF;
  531                 return (0);
  532 
  533         case DTYPE_FIFO:
  534         case DTYPE_VNODE:
  535                 vp = (struct vnode *)fp->f_data;
  536                 return (VOP_PATHCONF(vp, uap->name, retval));
  537 
  538         default:
  539                 panic("fpathconf");
  540         }
  541         /*NOTREACHED*/
  542 }
  543 
  544 /*
  545  * Allocate a file descriptor for the process.
  546  */
  547 static int fdexpand;
  548 SYSCTL_INT(_debug, OID_AUTO, fdexpand, CTLFLAG_RD, &fdexpand, 0, "");
  549 
  550 int
  551 fdalloc(p, want, result)
  552         struct proc *p;
  553         int want;
  554         int *result;
  555 {
  556         register struct filedesc *fdp = p->p_fd;
  557         register int i;
  558         int lim, last, nfiles;
  559         struct file **newofile;
  560         char *newofileflags;
  561 
  562         /*
  563          * Search for a free descriptor starting at the higher
  564          * of want or fd_freefile.  If that fails, consider
  565          * expanding the ofile array.
  566          */
  567         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
  568         for (;;) {
  569                 last = min(fdp->fd_nfiles, lim);
  570                 if ((i = want) < fdp->fd_freefile)
  571                         i = fdp->fd_freefile;
  572                 for (; i < last; i++) {
  573                         if (fdp->fd_ofiles[i] == NULL) {
  574                                 fdp->fd_ofileflags[i] = 0;
  575                                 if (i > fdp->fd_lastfile)
  576                                         fdp->fd_lastfile = i;
  577                                 if (want <= fdp->fd_freefile)
  578                                         fdp->fd_freefile = i;
  579                                 *result = i;
  580                                 return (0);
  581                         }
  582                 }
  583 
  584                 /*
  585                  * No space in current array.  Expand?
  586                  */
  587                 if (fdp->fd_nfiles >= lim)
  588                         return (EMFILE);
  589                 if (fdp->fd_nfiles < NDEXTENT)
  590                         nfiles = NDEXTENT;
  591                 else
  592                         nfiles = 2 * fdp->fd_nfiles;
  593                 MALLOC(newofile, struct file **, nfiles * OFILESIZE,
  594                     M_FILEDESC, M_WAITOK);
  595                 newofileflags = (char *) &newofile[nfiles];
  596                 /*
  597                  * Copy the existing ofile and ofileflags arrays
  598                  * and zero the new portion of each array.
  599                  */
  600                 bcopy(fdp->fd_ofiles, newofile,
  601                         (i = sizeof(struct file *) * fdp->fd_nfiles));
  602                 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
  603                 bcopy(fdp->fd_ofileflags, newofileflags,
  604                         (i = sizeof(char) * fdp->fd_nfiles));
  605                 bzero(newofileflags + i, nfiles * sizeof(char) - i);
  606                 if (fdp->fd_nfiles > NDFILE)
  607                         FREE(fdp->fd_ofiles, M_FILEDESC);
  608                 fdp->fd_ofiles = newofile;
  609                 fdp->fd_ofileflags = newofileflags;
  610                 fdp->fd_nfiles = nfiles;
  611                 fdexpand++;
  612         }
  613         return (0);
  614 }
  615 
  616 /*
  617  * Check to see whether n user file descriptors
  618  * are available to the process p.
  619  */
  620 int
  621 fdavail(p, n)
  622         struct proc *p;
  623         register int n;
  624 {
  625         register struct filedesc *fdp = p->p_fd;
  626         register struct file **fpp;
  627         register int i, lim, last;
  628 
  629         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
  630         if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
  631                 return (1);
  632 
  633         last = min(fdp->fd_nfiles, lim);
  634         fpp = &fdp->fd_ofiles[fdp->fd_freefile];
  635         for (i = last - fdp->fd_freefile; --i >= 0; fpp++)
  636                 if (*fpp == NULL && --n <= 0)
  637                         return (1);
  638         return (0);
  639 }
  640 
  641 /*
  642  * Create a new open file structure and allocate
  643  * a file decriptor for the process that refers to it.
  644  */
  645 int
  646 falloc(p, resultfp, resultfd)
  647         register struct proc *p;
  648         struct file **resultfp;
  649         int *resultfd;
  650 {
  651         register struct file *fp, *fq;
  652         int error, i;
  653 
  654         if ((error = fdalloc(p, 0, &i)))
  655                 return (error);
  656         if (nfiles >= maxfiles) {
  657                 tablefull("file");
  658                 return (ENFILE);
  659         }
  660         /*
  661          * Allocate a new file descriptor.
  662          * If the process has file descriptor zero open, add to the list
  663          * of open files at that point, otherwise put it at the front of
  664          * the list of open files.
  665          */
  666         nfiles++;
  667         MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
  668         bzero(fp, sizeof(struct file));
  669         if ((fq = p->p_fd->fd_ofiles[0])) {
  670                 LIST_INSERT_AFTER(fq, fp, f_list);
  671         } else {
  672                 LIST_INSERT_HEAD(&filehead, fp, f_list);
  673         }
  674         p->p_fd->fd_ofiles[i] = fp;
  675         fp->f_count = 1;
  676         fp->f_cred = p->p_ucred;
  677         crhold(fp->f_cred);
  678         if (resultfp)
  679                 *resultfp = fp;
  680         if (resultfd)
  681                 *resultfd = i;
  682         return (0);
  683 }
  684 
  685 /*
  686  * Free a file descriptor.
  687  */
  688 void
  689 ffree(fp)
  690         register struct file *fp;
  691 {
  692         LIST_REMOVE(fp, f_list);
  693         crfree(fp->f_cred);
  694 #ifdef DIAGNOSTIC
  695         fp->f_count = 0;
  696 #endif
  697         nfiles--;
  698         FREE(fp, M_FILE);
  699 }
  700 
  701 /*
  702  * Build a new filedesc structure.
  703  */
  704 struct filedesc *
  705 fdinit(p)
  706         struct proc *p;
  707 {
  708         register struct filedesc0 *newfdp;
  709         register struct filedesc *fdp = p->p_fd;
  710 
  711         MALLOC(newfdp, struct filedesc0 *, sizeof(struct filedesc0),
  712             M_FILEDESC, M_WAITOK);
  713         bzero(newfdp, sizeof(struct filedesc0));
  714         newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
  715         VREF(newfdp->fd_fd.fd_cdir);
  716         newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
  717         if (newfdp->fd_fd.fd_rdir)
  718                 VREF(newfdp->fd_fd.fd_rdir);
  719 
  720         /* Create the file descriptor table. */
  721         newfdp->fd_fd.fd_refcnt = 1;
  722         newfdp->fd_fd.fd_cmask = cmask;
  723         newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
  724         newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
  725         newfdp->fd_fd.fd_nfiles = NDFILE;
  726 
  727         newfdp->fd_fd.fd_freefile = 0;
  728         newfdp->fd_fd.fd_lastfile = 0;
  729 
  730         return (&newfdp->fd_fd);
  731 }
  732 
  733 /*
  734  * Share a filedesc structure.
  735  */
  736 struct filedesc *
  737 fdshare(p)
  738         struct proc *p;
  739 {
  740         p->p_fd->fd_refcnt++;
  741         return (p->p_fd);
  742 }
  743 
  744 /*
  745  * Copy a filedesc structure.
  746  */
  747 struct filedesc *
  748 fdcopy(p)
  749         struct proc *p;
  750 {
  751         register struct filedesc *newfdp, *fdp = p->p_fd;
  752         register struct file **fpp;
  753         register int i;
  754 
  755         MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
  756             M_FILEDESC, M_WAITOK);
  757         bcopy(fdp, newfdp, sizeof(struct filedesc));
  758         VREF(newfdp->fd_cdir);
  759         if (newfdp->fd_rdir)
  760                 VREF(newfdp->fd_rdir);
  761         newfdp->fd_refcnt = 1;
  762 
  763         /*
  764          * If the number of open files fits in the internal arrays
  765          * of the open file structure, use them, otherwise allocate
  766          * additional memory for the number of descriptors currently
  767          * in use.
  768          */
  769         if (newfdp->fd_lastfile < NDFILE) {
  770                 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
  771                 newfdp->fd_ofileflags =
  772                     ((struct filedesc0 *) newfdp)->fd_dfileflags;
  773                 i = NDFILE;
  774         } else {
  775                 /*
  776                  * Compute the smallest multiple of NDEXTENT needed
  777                  * for the file descriptors currently in use,
  778                  * allowing the table to shrink.
  779                  */
  780                 i = newfdp->fd_nfiles;
  781                 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
  782                         i /= 2;
  783                 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
  784                     M_FILEDESC, M_WAITOK);
  785                 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
  786         }
  787         newfdp->fd_nfiles = i;
  788         bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
  789         bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
  790         fpp = newfdp->fd_ofiles;
  791         for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
  792                 if (*fpp != NULL)
  793                         (*fpp)->f_count++;
  794         return (newfdp);
  795 }
  796 
  797 /*
  798  * Release a filedesc structure.
  799  */
  800 void
  801 fdfree(p)
  802         struct proc *p;
  803 {
  804         register struct filedesc *fdp = p->p_fd;
  805         struct file **fpp;
  806         register int i;
  807 
  808         if (--fdp->fd_refcnt > 0)
  809                 return;
  810         fpp = fdp->fd_ofiles;
  811         for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
  812                 if (*fpp)
  813                         (void) closef(*fpp, p);
  814         if (fdp->fd_nfiles > NDFILE)
  815                 FREE(fdp->fd_ofiles, M_FILEDESC);
  816         vrele(fdp->fd_cdir);
  817         if (fdp->fd_rdir)
  818                 vrele(fdp->fd_rdir);
  819         FREE(fdp, M_FILEDESC);
  820 }
  821 
  822 /*
  823  * Close any files on exec?
  824  */
  825 void
  826 fdcloseexec(p)
  827         struct proc *p;
  828 {
  829         struct filedesc *fdp = p->p_fd;
  830         struct file **fpp;
  831         char *fdfp;
  832         register int i;
  833 
  834         fpp = fdp->fd_ofiles;
  835         fdfp = fdp->fd_ofileflags;
  836         for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
  837                 if (*fpp != NULL && (*fdfp & UF_EXCLOSE)) {
  838                         if (*fdfp & UF_MAPPED)
  839                                 (void) munmapfd(p, i);
  840                         (void) closef(*fpp, p);
  841                         *fpp = NULL;
  842                         *fdfp = 0;
  843                         if (i < fdp->fd_freefile)
  844                                 fdp->fd_freefile = i;
  845                 }
  846         while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
  847                 fdp->fd_lastfile--;
  848 }
  849 
  850 /*
  851  * Internal form of close.
  852  * Decrement reference count on file structure.
  853  * Note: p may be NULL when closing a file
  854  * that was being passed in a message.
  855  */
  856 int
  857 closef(fp, p)
  858         register struct file *fp;
  859         register struct proc *p;
  860 {
  861         struct vnode *vp;
  862         struct flock lf;
  863         int error;
  864 
  865         if (fp == NULL)
  866                 return (0);
  867         /*
  868          * POSIX record locking dictates that any close releases ALL
  869          * locks owned by this process.  This is handled by setting
  870          * a flag in the unlock to free ONLY locks obeying POSIX
  871          * semantics, and not to free BSD-style file locks.
  872          * If the descriptor was in a message, POSIX-style locks
  873          * aren't passed with the descriptor.
  874          */
  875         if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
  876                 lf.l_whence = SEEK_SET;
  877                 lf.l_start = 0;
  878                 lf.l_len = 0;
  879                 lf.l_type = F_UNLCK;
  880                 vp = (struct vnode *)fp->f_data;
  881                 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
  882         }
  883         if (--fp->f_count > 0)
  884                 return (0);
  885         if (fp->f_count < 0)
  886                 panic("closef: count < 0");
  887         if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
  888                 lf.l_whence = SEEK_SET;
  889                 lf.l_start = 0;
  890                 lf.l_len = 0;
  891                 lf.l_type = F_UNLCK;
  892                 vp = (struct vnode *)fp->f_data;
  893                 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
  894         }
  895         if (fp->f_ops)
  896                 error = (*fp->f_ops->fo_close)(fp, p);
  897         else
  898                 error = 0;
  899         ffree(fp);
  900         return (error);
  901 }
  902 
  903 /*
  904  * Apply an advisory lock on a file descriptor.
  905  *
  906  * Just attempt to get a record lock of the requested type on
  907  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
  908  */
  909 #ifndef _SYS_SYSPROTO_H_
  910 struct flock_args {
  911         int     fd;
  912         int     how;
  913 };
  914 #endif
  915 /* ARGSUSED */
  916 int
  917 flock(p, uap, retval)
  918         struct proc *p;
  919         register struct flock_args *uap;
  920         int *retval;
  921 {
  922         register struct filedesc *fdp = p->p_fd;
  923         register struct file *fp;
  924         struct vnode *vp;
  925         struct flock lf;
  926 
  927         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  928             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  929                 return (EBADF);
  930         if (fp->f_type != DTYPE_VNODE)
  931                 return (EOPNOTSUPP);
  932         vp = (struct vnode *)fp->f_data;
  933         lf.l_whence = SEEK_SET;
  934         lf.l_start = 0;
  935         lf.l_len = 0;
  936         if (uap->how & LOCK_UN) {
  937                 lf.l_type = F_UNLCK;
  938                 fp->f_flag &= ~FHASLOCK;
  939                 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
  940         }
  941         if (uap->how & LOCK_EX)
  942                 lf.l_type = F_WRLCK;
  943         else if (uap->how & LOCK_SH)
  944                 lf.l_type = F_RDLCK;
  945         else
  946                 return (EBADF);
  947         fp->f_flag |= FHASLOCK;
  948         if (uap->how & LOCK_NB)
  949                 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
  950         return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
  951 }
  952 
  953 /*
  954  * File Descriptor pseudo-device driver (/dev/fd/).
  955  *
  956  * Opening minor device N dup()s the file (if any) connected to file
  957  * descriptor N belonging to the calling process.  Note that this driver
  958  * consists of only the ``open()'' routine, because all subsequent
  959  * references to this file will be direct to the other driver.
  960  */
  961 /* ARGSUSED */
  962 static int
  963 fdopen(dev, mode, type, p)
  964         dev_t dev;
  965         int mode, type;
  966         struct proc *p;
  967 {
  968 
  969         /*
  970          * XXX Kludge: set curproc->p_dupfd to contain the value of the
  971          * the file descriptor being sought for duplication. The error
  972          * return ensures that the vnode for this device will be released
  973          * by vn_open. Open will detect this special error and take the
  974          * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
  975          * will simply report the error.
  976          */
  977         p->p_dupfd = minor(dev);
  978         return (ENODEV);
  979 }
  980 
  981  /*
  982  * For setuid/setgid programs we don't want to people to use that setuidness
  983  * to generate error messages which write to a file which otherwise would 
  984  * otherwise be off limits to the proces.
  985  * 
  986  * This is a gross hack to plug the hole.  A better solution would involve
  987  * a special vop or other form of generalized access control mechanism.  We
  988  * go ahead and just reject all procfs file systems accesses as dangerous.
  989  *
  990  * Since setugidsafety calls this only for fd 0, 1 and 2, this check is
  991  * sufficient.  We also don't for setugidness since we know we are.
  992  */
  993 static int
  994 is_unsafe(struct file *fp)
  995 {
  996        if (fp->f_type == DTYPE_VNODE &&
  997            ((struct vnode *)(fp->f_data))->v_tag == VT_PROCFS)
  998                return (1);
  999        return (0);
 1000 }   
 1001 
 1002 /*
 1003  * Make this setguid thing safe, if at all possible.
 1004  */
 1005 void
 1006 setugidsafety(p)  
 1007        struct proc *p;
 1008 {
 1009        struct filedesc *fdp = p->p_fd;
 1010        struct file **fpp;
 1011        char *fdfp;
 1012        register int i;
 1013        
 1014        /* Certain daemons might not have file descriptors. */
 1015        if (fdp == NULL)
 1016                return;   
 1017                        
 1018        fpp = fdp->fd_ofiles;
 1019        fdfp = fdp->fd_ofileflags;
 1020        for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++) {
 1021                if (i > 2)
 1022                        break;
 1023                if (*fpp != NULL && is_unsafe(*fpp)) {
 1024                        if (*fdfp & UF_MAPPED)
 1025                                (void) munmapfd(p, i);
 1026                        (void) closef(*fpp, p); 
 1027                        *fpp = NULL;
 1028                        *fdfp = 0;
 1029                        if (i < fdp->fd_freefile)
 1030                                fdp->fd_freefile = i;
 1031                }
 1032        }
 1033        while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
 1034                fdp->fd_lastfile--;
 1035 }
 1036 
 1037 
 1038 /*
 1039  * Duplicate the specified descriptor to a free descriptor.
 1040  */
 1041 int
 1042 dupfdopen(fdp, indx, dfd, mode, error)
 1043         register struct filedesc *fdp;
 1044         register int indx, dfd;
 1045         int mode;
 1046         int error;
 1047 {
 1048         register struct file *wfp;
 1049         struct file *fp;
 1050 
 1051         /*
 1052          * If the to-be-dup'd fd number is greater than the allowed number
 1053          * of file descriptors, or the fd to be dup'd has already been
 1054          * closed, reject.  Note, check for new == old is necessary as
 1055          * falloc could allocate an already closed to-be-dup'd descriptor
 1056          * as the new descriptor.
 1057          */
 1058         fp = fdp->fd_ofiles[indx];
 1059         if ((u_int)dfd >= fdp->fd_nfiles ||
 1060             (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
 1061                 return (EBADF);
 1062 
 1063         /*
 1064          * There are two cases of interest here.
 1065          *
 1066          * For ENODEV simply dup (dfd) to file descriptor
 1067          * (indx) and return.
 1068          *
 1069          * For ENXIO steal away the file structure from (dfd) and
 1070          * store it in (indx).  (dfd) is effectively closed by
 1071          * this operation.
 1072          *
 1073          * Any other error code is just returned.
 1074          */
 1075         switch (error) {
 1076         case ENODEV:
 1077                 /*
 1078                  * Check that the mode the file is being opened for is a
 1079                  * subset of the mode of the existing descriptor.
 1080                  */
 1081                 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
 1082                         return (EACCES);
 1083                 fdp->fd_ofiles[indx] = wfp;
 1084                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 1085                 wfp->f_count++;
 1086                 if (indx > fdp->fd_lastfile)
 1087                         fdp->fd_lastfile = indx;
 1088                 return (0);
 1089 
 1090         case ENXIO:
 1091                 /*
 1092                  * Steal away the file pointer from dfd, and stuff it into indx.
 1093                  */
 1094                 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
 1095                 fdp->fd_ofiles[dfd] = NULL;
 1096                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 1097                 fdp->fd_ofileflags[dfd] = 0;
 1098                 /*
 1099                  * Complete the clean up of the filedesc structure by
 1100                  * recomputing the various hints.
 1101                  */
 1102                 if (indx > fdp->fd_lastfile)
 1103                         fdp->fd_lastfile = indx;
 1104                 else
 1105                         while (fdp->fd_lastfile > 0 &&
 1106                                fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
 1107                                 fdp->fd_lastfile--;
 1108                         if (dfd < fdp->fd_freefile)
 1109                                 fdp->fd_freefile = dfd;
 1110                 return (0);
 1111 
 1112         default:
 1113                 return (error);
 1114         }
 1115         /* NOTREACHED */
 1116 }
 1117 
 1118 /*
 1119  * Get file structures.
 1120  */
 1121 static int
 1122 sysctl_kern_file SYSCTL_HANDLER_ARGS
 1123 {
 1124         int error;
 1125         struct file *fp;
 1126 
 1127         if (!req->oldptr) {
 1128                 /*
 1129                  * overestimate by 10 files
 1130                  */
 1131                 return (SYSCTL_OUT(req, 0, sizeof(filehead) + 
 1132                                 (nfiles + 10) * sizeof(struct file)));
 1133         }
 1134 
 1135         error = SYSCTL_OUT(req, (caddr_t)&filehead, sizeof(filehead));
 1136         if (error)
 1137                 return (error);
 1138 
 1139         /*
 1140          * followed by an array of file structures
 1141          */
 1142         for (fp = filehead.lh_first; fp != NULL; fp = fp->f_list.le_next) {
 1143                 error = SYSCTL_OUT(req, (caddr_t)fp, sizeof (struct file));
 1144                 if (error)
 1145                         return (error);
 1146         }
 1147         return (0);
 1148 }
 1149 
 1150 SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD,
 1151         0, 0, sysctl_kern_file, "S,file", "");
 1152 
 1153 SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc,
 1154         CTLFLAG_RW, &maxfilesperproc, 0, "");
 1155 
 1156 SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, &maxfiles, 0, "");
 1157 
 1158 static fildesc_devsw_installed = 0;
 1159 #ifdef DEVFS
 1160 static  void *devfs_token_stdin;
 1161 static  void *devfs_token_stdout;
 1162 static  void *devfs_token_stderr;
 1163 static  void *devfs_token_fildesc[NUMFDESC];
 1164 #endif
 1165 
 1166 static void     fildesc_drvinit(void *unused)
 1167 {
 1168         dev_t dev;
 1169 #ifdef DEVFS
 1170         int fd;
 1171 #endif
 1172 
 1173         if( ! fildesc_devsw_installed ) {
 1174                 dev = makedev(CDEV_MAJOR,0);
 1175                 cdevsw_add(&dev,&fildesc_cdevsw,NULL);
 1176                 fildesc_devsw_installed = 1;
 1177 #ifdef DEVFS
 1178                 for (fd = 0; fd < NUMFDESC; fd++)
 1179                         devfs_token_fildesc[fd] =
 1180                                 devfs_add_devswf(&fildesc_cdevsw, fd, DV_CHR,
 1181                                                  UID_BIN, GID_BIN, 0666,
 1182                                                  "fd/%d", fd);
 1183                 devfs_token_stdin =
 1184                         devfs_add_devswf(&fildesc_cdevsw, 0, DV_CHR,
 1185                                          UID_ROOT, GID_WHEEL, 0666,
 1186                                          "stdin", fd);
 1187                 devfs_token_stdout =
 1188                         devfs_add_devswf(&fildesc_cdevsw, 1, DV_CHR,
 1189                                          UID_ROOT, GID_WHEEL, 0666,
 1190                                          "stdout", fd);
 1191                 devfs_token_stderr =
 1192                         devfs_add_devswf(&fildesc_cdevsw, 2, DV_CHR,
 1193                                          UID_ROOT, GID_WHEEL, 0666,
 1194                                          "stderr", fd);
 1195 #endif
 1196         }
 1197 }
 1198 
 1199 SYSINIT(fildescdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,
 1200                                         fildesc_drvinit,NULL)
 1201 
 1202 

Cache object: 054207ddc4cda0b8de80405a6b75568f


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