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

Cache object: 6360aa79c0406e1cfb6f6621a726f452


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