root/kern/kern_descrip.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. filedesc_init
  2. find_next_zero
  3. find_last_set
  4. fd_used
  5. fd_unused
  6. fd_getfile
  7. sys_dup
  8. sys_dup2
  9. sys_fcntl
  10. finishdup
  11. fdremove
  12. fdrelease
  13. sys_close
  14. sys_fstat
  15. sys_fpathconf
  16. fdalloc
  17. fdexpand
  18. falloc
  19. fdinit
  20. fdshare
  21. fdcopy
  22. fdfree
  23. closef
  24. sys_flock
  25. filedescopen
  26. dupfdopen
  27. fdcloseexec
  28. sys_closefrom

    1 /*      $OpenBSD: kern_descrip.c,v 1.76 2007/03/15 10:22:30 art Exp $   */
    2 /*      $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $       */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1989, 1991, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  * (c) UNIX System Laboratories, Inc.
    8  * All or some portions of this file are derived from material licensed
    9  * to the University of California by American Telephone and Telegraph
   10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   11  * the permission of UNIX System Laboratories, Inc.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)kern_descrip.c      8.6 (Berkeley) 4/19/94
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/filedesc.h>
   43 #include <sys/kernel.h>
   44 #include <sys/vnode.h>
   45 #include <sys/proc.h>
   46 #include <sys/file.h>
   47 #include <sys/socket.h>
   48 #include <sys/socketvar.h>
   49 #include <sys/stat.h>
   50 #include <sys/ioctl.h>
   51 #include <sys/fcntl.h>
   52 #include <sys/malloc.h>
   53 #include <sys/syslog.h>
   54 #include <sys/ucred.h>
   55 #include <sys/unistd.h>
   56 #include <sys/resourcevar.h>
   57 #include <sys/conf.h>
   58 #include <sys/mount.h>
   59 #include <sys/syscallargs.h>
   60 #include <sys/event.h>
   61 #include <sys/pool.h>
   62 
   63 #include <uvm/uvm_extern.h>
   64 
   65 #include <sys/pipe.h>
   66 
   67 /*
   68  * Descriptor management.
   69  */
   70 struct filelist filehead;       /* head of list of open files */
   71 int nfiles;                     /* actual number of open files */
   72 
   73 static __inline void fd_used(struct filedesc *, int);
   74 static __inline void fd_unused(struct filedesc *, int);
   75 static __inline int find_next_zero(u_int *, int, u_int);
   76 int finishdup(struct proc *, struct file *, int, int, register_t *);
   77 int find_last_set(struct filedesc *, int);
   78 
   79 struct pool file_pool;
   80 struct pool fdesc_pool;
   81 
   82 void
   83 filedesc_init(void)
   84 {
   85         pool_init(&file_pool, sizeof(struct file), 0, 0, 0, "filepl",
   86                 &pool_allocator_nointr);
   87         pool_init(&fdesc_pool, sizeof(struct filedesc0), 0, 0, 0, "fdescpl",
   88                 &pool_allocator_nointr);
   89         LIST_INIT(&filehead);
   90 }
   91 
   92 static __inline int
   93 find_next_zero (u_int *bitmap, int want, u_int bits)
   94 {
   95         int i, off, maxoff;
   96         u_int sub;
   97 
   98         if (want > bits)
   99                 return -1;
  100 
  101         off = want >> NDENTRYSHIFT;
  102         i = want & NDENTRYMASK;
  103         if (i) {
  104                 sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i));
  105                 if (sub != ~0)
  106                         goto found;
  107                 off++;
  108         }
  109 
  110         maxoff = NDLOSLOTS(bits);
  111         while (off < maxoff) {
  112                 if ((sub = bitmap[off]) != ~0)
  113                         goto found;
  114                 off++;
  115         }
  116 
  117         return -1;
  118 
  119  found:
  120         return (off << NDENTRYSHIFT) + ffs(~sub) - 1;
  121 }
  122 
  123 int
  124 find_last_set(struct filedesc *fd, int last)
  125 {
  126         int off, i;
  127         struct file **ofiles = fd->fd_ofiles;
  128         u_int *bitmap = fd->fd_lomap;
  129 
  130         off = (last - 1) >> NDENTRYSHIFT;
  131 
  132         while (off >= 0 && !bitmap[off])
  133                 off--;
  134         if (off < 0)
  135                 return 0;
  136 
  137         i = ((off + 1) << NDENTRYSHIFT) - 1;
  138         if (i >= last)
  139                 i = last - 1;
  140 
  141         while (i > 0 && ofiles[i] == NULL)
  142                 i--;
  143         return i;
  144 }
  145 
  146 static __inline void
  147 fd_used(struct filedesc *fdp, int fd)
  148 {
  149         u_int off = fd >> NDENTRYSHIFT;
  150 
  151         fdp->fd_lomap[off] |= 1 << (fd & NDENTRYMASK);
  152         if (fdp->fd_lomap[off] == ~0)
  153                 fdp->fd_himap[off >> NDENTRYSHIFT] |= 1 << (off & NDENTRYMASK);
  154 
  155         if (fd > fdp->fd_lastfile)
  156                 fdp->fd_lastfile = fd;
  157 }
  158 
  159 static __inline void
  160 fd_unused(struct filedesc *fdp, int fd)
  161 {
  162         u_int off = fd >> NDENTRYSHIFT;
  163 
  164         if (fd < fdp->fd_freefile)
  165                 fdp->fd_freefile = fd;
  166 
  167         if (fdp->fd_lomap[off] == ~0)
  168                 fdp->fd_himap[off >> NDENTRYSHIFT] &= ~(1 << (off & NDENTRYMASK));
  169         fdp->fd_lomap[off] &= ~(1 << (fd & NDENTRYMASK));
  170 
  171 #ifdef DIAGNOSTIC
  172         if (fd > fdp->fd_lastfile)
  173                 panic("fd_unused: fd_lastfile inconsistent");
  174 #endif
  175         if (fd == fdp->fd_lastfile)
  176                 fdp->fd_lastfile = find_last_set(fdp, fd);
  177 }
  178 
  179 struct file *
  180 fd_getfile(struct filedesc *fdp, int fd)
  181 {
  182         struct file *fp;
  183 
  184         if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
  185                 return (NULL);
  186 
  187         if (!FILE_IS_USABLE(fp))
  188                 return (NULL);
  189 
  190         return (fp);
  191 }
  192 
  193 /*
  194  * System calls on descriptors.
  195  */
  196 
  197 /*
  198  * Duplicate a file descriptor.
  199  */
  200 /* ARGSUSED */
  201 int
  202 sys_dup(struct proc *p, void *v, register_t *retval)
  203 {
  204         struct sys_dup_args /* {
  205                 syscallarg(int) fd;
  206         } */ *uap = v;
  207         struct filedesc *fdp = p->p_fd;
  208         int old = SCARG(uap, fd);
  209         struct file *fp;
  210         int new;
  211         int error;
  212 
  213 restart:
  214         if ((fp = fd_getfile(fdp, old)) == NULL)
  215                 return (EBADF);
  216         FREF(fp);
  217         fdplock(fdp);
  218         if ((error = fdalloc(p, 0, &new)) != 0) {
  219                 FRELE(fp);
  220                 if (error == ENOSPC) {
  221                         fdexpand(p);
  222                         fdpunlock(fdp);
  223                         goto restart;
  224                 }
  225                 goto out;
  226         }
  227         error = finishdup(p, fp, old, new, retval);
  228 
  229 out:
  230         fdpunlock(fdp);
  231         return (error);
  232 }
  233 
  234 /*
  235  * Duplicate a file descriptor to a particular value.
  236  */
  237 /* ARGSUSED */
  238 int
  239 sys_dup2(struct proc *p, void *v, register_t *retval)
  240 {
  241         struct sys_dup2_args /* {
  242                 syscallarg(int) from;
  243                 syscallarg(int) to;
  244         } */ *uap = v;
  245         int old = SCARG(uap, from), new = SCARG(uap, to);
  246         struct filedesc *fdp = p->p_fd;
  247         struct file *fp;
  248         int i, error;
  249 
  250 restart:
  251         if ((fp = fd_getfile(fdp, old)) == NULL)
  252                 return (EBADF);
  253         if ((u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  254             (u_int)new >= maxfiles)
  255                 return (EBADF);
  256         if (old == new) {
  257                 /*
  258                  * NOTE! This doesn't clear the close-on-exec flag. This might
  259                  * or might not be the intended behavior from the start, but
  260                  * this is what everyone else does.
  261                  */
  262                 *retval = new;
  263                 return (0);
  264         }
  265         FREF(fp);
  266         fdplock(fdp);
  267         if (new >= fdp->fd_nfiles) {
  268                 if ((error = fdalloc(p, new, &i)) != 0) {
  269                         FRELE(fp);
  270                         if (error == ENOSPC) {
  271                                 fdexpand(p);
  272                                 fdpunlock(fdp);
  273                                 goto restart;
  274                         }
  275                         goto out;
  276                 }
  277                 if (new != i)
  278                         panic("dup2: fdalloc");
  279         }
  280         /* finishdup() does FRELE */
  281         error = finishdup(p, fp, old, new, retval);
  282 
  283 out:
  284         fdpunlock(fdp);
  285         return (error);
  286 }
  287 
  288 /*
  289  * The file control system call.
  290  */
  291 /* ARGSUSED */
  292 int
  293 sys_fcntl(struct proc *p, void *v, register_t *retval)
  294 {
  295         struct sys_fcntl_args /* {
  296                 syscallarg(int) fd;
  297                 syscallarg(int) cmd;
  298                 syscallarg(void *) arg;
  299         } */ *uap = v;
  300         int fd = SCARG(uap, fd);
  301         struct filedesc *fdp = p->p_fd;
  302         struct file *fp;
  303         struct vnode *vp;
  304         int i, tmp, newmin, flg = F_POSIX;
  305         struct flock fl;
  306         int error = 0;
  307 
  308 restart:
  309         if ((fp = fd_getfile(fdp, fd)) == NULL)
  310                 return (EBADF);
  311         FREF(fp);
  312         switch (SCARG(uap, cmd)) {
  313 
  314         case F_DUPFD:
  315                 newmin = (long)SCARG(uap, arg);
  316                 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  317                     (u_int)newmin >= maxfiles) {
  318                         error = EINVAL;
  319                         break;
  320                 }
  321                 fdplock(fdp);
  322                 if ((error = fdalloc(p, newmin, &i)) != 0) {
  323                         if (error == ENOSPC) {
  324                                 fdexpand(p);
  325                                 FRELE(fp);
  326                                 fdpunlock(fdp);
  327                                 goto restart;
  328                         }
  329                 }
  330                 /* finishdup will FRELE for us. */
  331                 if (!error)
  332                         error = finishdup(p, fp, fd, i, retval);
  333                 else
  334                         FRELE(fp);
  335 
  336                 fdpunlock(fdp);
  337                 return (error);
  338 
  339         case F_GETFD:
  340                 *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
  341                 break;
  342 
  343         case F_SETFD:
  344                 if ((long)SCARG(uap, arg) & 1)
  345                         fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
  346                 else
  347                         fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
  348                 break;
  349 
  350         case F_GETFL:
  351                 *retval = OFLAGS(fp->f_flag);
  352                 break;
  353 
  354         case F_SETFL:
  355                 fp->f_flag &= ~FCNTLFLAGS;
  356                 fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
  357                 tmp = fp->f_flag & FNONBLOCK;
  358                 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  359                 if (error)
  360                         break;
  361                 tmp = fp->f_flag & FASYNC;
  362                 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
  363                 if (!error)
  364                         break;
  365                 fp->f_flag &= ~FNONBLOCK;
  366                 tmp = 0;
  367                 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  368                 break;
  369 
  370         case F_GETOWN:
  371                 if (fp->f_type == DTYPE_SOCKET) {
  372                         *retval = ((struct socket *)fp->f_data)->so_pgid;
  373                         break;
  374                 }
  375                 error = (*fp->f_ops->fo_ioctl)
  376                         (fp, TIOCGPGRP, (caddr_t)&tmp, p);
  377                 *retval = -tmp;
  378                 break;
  379 
  380         case F_SETOWN:
  381                 if (fp->f_type == DTYPE_SOCKET) {
  382                         struct socket *so = (struct socket *)fp->f_data;
  383 
  384                         so->so_pgid = (long)SCARG(uap, arg);
  385                         so->so_siguid = p->p_cred->p_ruid;
  386                         so->so_sigeuid = p->p_ucred->cr_uid;
  387                         break;
  388                 }
  389                 if ((long)SCARG(uap, arg) <= 0) {
  390                         SCARG(uap, arg) = (void *)(-(long)SCARG(uap, arg));
  391                 } else {
  392                         struct proc *p1 = pfind((long)SCARG(uap, arg));
  393                         if (p1 == 0) {
  394                                 error = ESRCH;
  395                                 break;
  396                         }
  397                         SCARG(uap, arg) = (void *)(long)p1->p_pgrp->pg_id;
  398                 }
  399                 error = ((*fp->f_ops->fo_ioctl)
  400                         (fp, TIOCSPGRP, (caddr_t)&SCARG(uap, arg), p));
  401                 break;
  402 
  403         case F_SETLKW:
  404                 flg |= F_WAIT;
  405                 /* FALLTHROUGH */
  406 
  407         case F_SETLK:
  408                 if (fp->f_type != DTYPE_VNODE) {
  409                         error = EBADF;
  410                         break;
  411                 }
  412                 vp = (struct vnode *)fp->f_data;
  413                 /* Copy in the lock structure */
  414                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
  415                     sizeof (fl));
  416                 if (error)
  417                         break;
  418                 if (fl.l_whence == SEEK_CUR) {
  419                         if (fl.l_start == 0 && fl.l_len < 0) {
  420                                 /* lockf(3) compliance hack */
  421                                 fl.l_len = -fl.l_len;
  422                                 fl.l_start = fp->f_offset - fl.l_len;
  423                         } else
  424                                 fl.l_start += fp->f_offset;
  425                 }
  426                 switch (fl.l_type) {
  427 
  428                 case F_RDLCK:
  429                         if ((fp->f_flag & FREAD) == 0) {
  430                                 error = EBADF;
  431                                 goto out;
  432                         }
  433                         atomic_setbits_int(&p->p_flag, P_ADVLOCK);
  434                         error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  435                         goto out;
  436 
  437                 case F_WRLCK:
  438                         if ((fp->f_flag & FWRITE) == 0) {
  439                                 error = EBADF;
  440                                 goto out;
  441                         }
  442                         atomic_setbits_int(&p->p_flag, P_ADVLOCK);
  443                         error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  444                         goto out;
  445 
  446                 case F_UNLCK:
  447                         error = (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
  448                                 F_POSIX));
  449                         goto out;
  450 
  451                 default:
  452                         error = EINVAL;
  453                         goto out;
  454                 }
  455 
  456         case F_GETLK:
  457                 if (fp->f_type != DTYPE_VNODE) {
  458                         error = EBADF;
  459                         break;
  460                 }
  461                 vp = (struct vnode *)fp->f_data;
  462                 /* Copy in the lock structure */
  463                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
  464                     sizeof (fl));
  465                 if (error)
  466                         break;
  467                 if (fl.l_whence == SEEK_CUR) {
  468                         if (fl.l_start == 0 && fl.l_len < 0) {
  469                                 /* lockf(3) compliance hack */
  470                                 fl.l_len = -fl.l_len;
  471                                 fl.l_start = fp->f_offset - fl.l_len;
  472                         } else
  473                                 fl.l_start += fp->f_offset;
  474                 }
  475                 if (fl.l_type != F_RDLCK &&
  476                     fl.l_type != F_WRLCK &&
  477                     fl.l_type != F_UNLCK &&
  478                     fl.l_type != 0) {
  479                         error = EINVAL;
  480                         break;
  481                 }
  482                 error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX);
  483                 if (error)
  484                         break;
  485                 error = (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg),
  486                     sizeof (fl)));
  487                 break;
  488 
  489         default:
  490                 error = EINVAL;
  491                 break;
  492         }
  493 out:
  494         FRELE(fp);
  495         return (error); 
  496 }
  497 
  498 /*
  499  * Common code for dup, dup2, and fcntl(F_DUPFD).
  500  */
  501 int
  502 finishdup(struct proc *p, struct file *fp, int old, int new, register_t *retval)
  503 {
  504         struct file *oldfp;
  505         struct filedesc *fdp = p->p_fd;
  506 
  507         if (fp->f_count == LONG_MAX-2) {
  508                 FRELE(fp);
  509                 return (EDEADLK);
  510         }
  511 
  512         /*
  513          * Don't fd_getfile here. We want to closef LARVAL files and
  514          * closef can deal with that.
  515          */
  516         oldfp = fdp->fd_ofiles[new];
  517         if (oldfp != NULL)
  518                 FREF(oldfp);
  519 
  520         fdp->fd_ofiles[new] = fp;
  521         fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
  522         fp->f_count++;
  523         FRELE(fp);
  524         if (oldfp == NULL)
  525                 fd_used(fdp, new);
  526         *retval = new;
  527 
  528         if (oldfp != NULL) {
  529                 if (new < fdp->fd_knlistsize)
  530                         knote_fdclose(p, new);
  531                 closef(oldfp, p);
  532         }
  533 
  534         return (0);
  535 }
  536 
  537 void
  538 fdremove(struct filedesc *fdp, int fd)
  539 {
  540         fdp->fd_ofiles[fd] = NULL;
  541         fd_unused(fdp, fd);
  542 }
  543 
  544 int
  545 fdrelease(struct proc *p, int fd)
  546 {
  547         struct filedesc *fdp = p->p_fd;
  548         struct file **fpp, *fp;
  549 
  550         /*
  551          * Don't fd_getfile here. We want to closef LARVAL files and closef
  552          * can deal with that.
  553          */
  554         fpp = &fdp->fd_ofiles[fd];
  555         fp = *fpp;
  556         if (fp == NULL)
  557                 return (EBADF);
  558         FREF(fp);
  559         *fpp = NULL;
  560         fdp->fd_ofileflags[fd] = 0;
  561         fd_unused(fdp, fd);
  562         if (fd < fdp->fd_knlistsize)
  563                 knote_fdclose(p, fd);
  564         return (closef(fp, p));
  565 }
  566 
  567 /*
  568  * Close a file descriptor.
  569  */
  570 /* ARGSUSED */
  571 int
  572 sys_close(struct proc *p, void *v, register_t *retval)
  573 {
  574         struct sys_close_args /* {
  575                 syscallarg(int) fd;
  576         } */ *uap = v;
  577         int fd = SCARG(uap, fd), error;
  578         struct filedesc *fdp = p->p_fd;
  579 
  580         if (fd_getfile(fdp, fd) == NULL)
  581                 return (EBADF);
  582         fdplock(fdp);
  583         error = fdrelease(p, fd);
  584         fdpunlock(fdp);
  585 
  586         return (error);
  587 }
  588 
  589 /*
  590  * Return status information about a file descriptor.
  591  */
  592 /* ARGSUSED */
  593 int
  594 sys_fstat(struct proc *p, void *v, register_t *retval)
  595 {
  596         struct sys_fstat_args /* {
  597                 syscallarg(int) fd;
  598                 syscallarg(struct stat *) sb;
  599         } */ *uap = v;
  600         int fd = SCARG(uap, fd);
  601         struct filedesc *fdp = p->p_fd;
  602         struct file *fp;
  603         struct stat ub;
  604         int error;
  605 
  606         if ((fp = fd_getfile(fdp, fd)) == NULL)
  607                 return (EBADF);
  608         FREF(fp);
  609         error = (*fp->f_ops->fo_stat)(fp, &ub, p);
  610         FRELE(fp);
  611         if (error == 0) {
  612                 /* 
  613                  * Don't let non-root see generation numbers
  614                  * (for NFS security)
  615                  */
  616                 if (suser(p, 0))
  617                         ub.st_gen = 0;
  618                 error = copyout((caddr_t)&ub, (caddr_t)SCARG(uap, sb),
  619                     sizeof (ub));
  620         }
  621         return (error);
  622 }
  623 
  624 /*
  625  * Return pathconf information about a file descriptor.
  626  */
  627 /* ARGSUSED */
  628 int
  629 sys_fpathconf(struct proc *p, void *v, register_t *retval)
  630 {
  631         struct sys_fpathconf_args /* {
  632                 syscallarg(int) fd;
  633                 syscallarg(int) name;
  634         } */ *uap = v;
  635         int fd = SCARG(uap, fd);
  636         struct filedesc *fdp = p->p_fd;
  637         struct file *fp;
  638         struct vnode *vp;
  639         int error;
  640 
  641         if ((fp = fd_getfile(fdp, fd)) == NULL)
  642                 return (EBADF);
  643         FREF(fp);
  644         switch (fp->f_type) {
  645         case DTYPE_PIPE:
  646         case DTYPE_SOCKET:
  647                 if (SCARG(uap, name) != _PC_PIPE_BUF) {
  648                         error = EINVAL;
  649                         break;
  650                 }
  651                 *retval = PIPE_BUF;
  652                 error = 0;
  653                 break;
  654 
  655         case DTYPE_VNODE:
  656                 vp = (struct vnode *)fp->f_data;
  657                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  658                 error = VOP_PATHCONF(vp, SCARG(uap, name), retval);
  659                 VOP_UNLOCK(vp, 0, p);
  660                 break;
  661 
  662         default:
  663                 error = EOPNOTSUPP;
  664                 break;
  665         }
  666         FRELE(fp);
  667         return (error);
  668 }
  669 
  670 /*
  671  * Allocate a file descriptor for the process.
  672  */
  673 int
  674 fdalloc(struct proc *p, int want, int *result)
  675 {
  676         struct filedesc *fdp = p->p_fd;
  677         int lim, last, i;
  678         u_int new, off;
  679 
  680         /*
  681          * Search for a free descriptor starting at the higher
  682          * of want or fd_freefile.  If that fails, consider
  683          * expanding the ofile array.
  684          */
  685 restart:
  686         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
  687         last = min(fdp->fd_nfiles, lim);
  688         if ((i = want) < fdp->fd_freefile)
  689                 i = fdp->fd_freefile;
  690         off = i >> NDENTRYSHIFT;
  691         new = find_next_zero(fdp->fd_himap, off,
  692             (last + NDENTRIES - 1) >> NDENTRYSHIFT);
  693         if (new != -1) {
  694                 i = find_next_zero(&fdp->fd_lomap[new], 
  695                                    new > off ? 0 : i & NDENTRYMASK,
  696                                    NDENTRIES);
  697                 if (i == -1) {
  698                         /*
  699                          * Free file descriptor in this block was
  700                          * below want, try again with higher want.
  701                          */
  702                         want = (new + 1) << NDENTRYSHIFT;
  703                         goto restart;
  704                 }
  705                 i += (new << NDENTRYSHIFT);
  706                 if (i < last) {
  707                         fd_used(fdp, i);
  708                         if (want <= fdp->fd_freefile)
  709                                 fdp->fd_freefile = i;
  710                         *result = i;
  711                         return (0);
  712                 }
  713         }
  714         if (fdp->fd_nfiles >= lim)
  715                 return (EMFILE);
  716 
  717         return (ENOSPC);
  718 }
  719 
  720 void
  721 fdexpand(struct proc *p)
  722 {
  723         struct filedesc *fdp = p->p_fd;
  724         int nfiles, i;
  725         struct file **newofile;
  726         char *newofileflags;
  727         u_int *newhimap, *newlomap;
  728 
  729         /*
  730          * No space in current array.
  731          */
  732         if (fdp->fd_nfiles < NDEXTENT)
  733                 nfiles = NDEXTENT;
  734         else
  735                 nfiles = 2 * fdp->fd_nfiles;
  736 
  737         newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK);
  738         newofileflags = (char *) &newofile[nfiles];
  739 
  740         /*
  741          * Copy the existing ofile and ofileflags arrays
  742          * and zero the new portion of each array.
  743          */
  744         bcopy(fdp->fd_ofiles, newofile,
  745                 (i = sizeof(struct file *) * fdp->fd_nfiles));
  746         bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
  747         bcopy(fdp->fd_ofileflags, newofileflags,
  748                 (i = sizeof(char) * fdp->fd_nfiles));
  749         bzero(newofileflags + i, nfiles * sizeof(char) - i);
  750 
  751         if (fdp->fd_nfiles > NDFILE)
  752                 free(fdp->fd_ofiles, M_FILEDESC);
  753 
  754         if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
  755                 newhimap = malloc(NDHISLOTS(nfiles) * sizeof(u_int),
  756                     M_FILEDESC, M_WAITOK);
  757                 newlomap = malloc(NDLOSLOTS(nfiles) * sizeof(u_int),
  758                     M_FILEDESC, M_WAITOK);
  759 
  760                 bcopy(fdp->fd_himap, newhimap,
  761                     (i = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int)));
  762                 bzero((char *)newhimap + i,
  763                     NDHISLOTS(nfiles) * sizeof(u_int) - i);
  764 
  765                 bcopy(fdp->fd_lomap, newlomap,
  766                     (i = NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int)));
  767                 bzero((char *)newlomap + i,
  768                     NDLOSLOTS(nfiles) * sizeof(u_int) - i);
  769 
  770                 if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
  771                         free(fdp->fd_himap, M_FILEDESC);
  772                         free(fdp->fd_lomap, M_FILEDESC);
  773                 }
  774                 fdp->fd_himap = newhimap;
  775                 fdp->fd_lomap = newlomap;
  776         }
  777         fdp->fd_ofiles = newofile;
  778         fdp->fd_ofileflags = newofileflags;
  779         fdp->fd_nfiles = nfiles;        
  780 }
  781 
  782 /*
  783  * Create a new open file structure and allocate
  784  * a file descriptor for the process that refers to it.
  785  */
  786 int
  787 falloc(struct proc *p, struct file **resultfp, int *resultfd)
  788 {
  789         struct file *fp, *fq;
  790         int error, i;
  791 
  792 restart:
  793         if ((error = fdalloc(p, 0, &i)) != 0) {
  794                 if (error == ENOSPC) {
  795                         fdexpand(p);
  796                         goto restart;
  797                 }
  798                 return (error);
  799         }
  800         if (nfiles >= maxfiles) {
  801                 fd_unused(p->p_fd, i);
  802                 tablefull("file");
  803                 return (ENFILE);
  804         }
  805         /*
  806          * Allocate a new file descriptor.
  807          * If the process has file descriptor zero open, add to the list
  808          * of open files at that point, otherwise put it at the front of
  809          * the list of open files.
  810          */
  811         nfiles++;
  812         fp = pool_get(&file_pool, PR_WAITOK);
  813         bzero(fp, sizeof(struct file));
  814         fp->f_iflags = FIF_LARVAL;
  815         if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
  816                 LIST_INSERT_AFTER(fq, fp, f_list);
  817         } else {
  818                 LIST_INSERT_HEAD(&filehead, fp, f_list);
  819         }
  820         p->p_fd->fd_ofiles[i] = fp;
  821         fp->f_count = 1;
  822         fp->f_cred = p->p_ucred;
  823         crhold(fp->f_cred);
  824         if (resultfp)
  825                 *resultfp = fp;
  826         if (resultfd)
  827                 *resultfd = i;
  828         FREF(fp);
  829         return (0);
  830 }
  831 
  832 /*
  833  * Build a new filedesc structure.
  834  */
  835 struct filedesc *
  836 fdinit(struct proc *p)
  837 {
  838         struct filedesc0 *newfdp;
  839         extern int cmask;
  840 
  841         newfdp = pool_get(&fdesc_pool, PR_WAITOK);
  842         bzero(newfdp, sizeof(struct filedesc0));
  843         if (p != NULL) {
  844                 struct filedesc *fdp = p->p_fd;
  845 
  846                 newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
  847                 VREF(newfdp->fd_fd.fd_cdir);
  848                 newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
  849                 if (newfdp->fd_fd.fd_rdir)
  850                         VREF(newfdp->fd_fd.fd_rdir);
  851         }
  852         rw_init(&newfdp->fd_fd.fd_lock, "fdlock");
  853 
  854         /* Create the file descriptor table. */
  855         newfdp->fd_fd.fd_refcnt = 1;
  856         newfdp->fd_fd.fd_cmask = cmask;
  857         newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
  858         newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
  859         newfdp->fd_fd.fd_nfiles = NDFILE;
  860         newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
  861         newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
  862         newfdp->fd_fd.fd_knlistsize = -1;
  863 
  864         newfdp->fd_fd.fd_freefile = 0;
  865         newfdp->fd_fd.fd_lastfile = 0;
  866 
  867         return (&newfdp->fd_fd);
  868 }
  869 
  870 /*
  871  * Share a filedesc structure.
  872  */
  873 struct filedesc *
  874 fdshare(struct proc *p)
  875 {
  876         p->p_fd->fd_refcnt++;
  877         return (p->p_fd);
  878 }
  879 
  880 /*
  881  * Copy a filedesc structure.
  882  */
  883 struct filedesc *
  884 fdcopy(struct proc *p)
  885 {
  886         struct filedesc *newfdp, *fdp = p->p_fd;
  887         struct file **fpp;
  888         int i;
  889 
  890         newfdp = pool_get(&fdesc_pool, PR_WAITOK);
  891         bcopy(fdp, newfdp, sizeof(struct filedesc));
  892         if (newfdp->fd_cdir)
  893                 VREF(newfdp->fd_cdir);
  894         if (newfdp->fd_rdir)
  895                 VREF(newfdp->fd_rdir);
  896         newfdp->fd_refcnt = 1;
  897 
  898         /*
  899          * If the number of open files fits in the internal arrays
  900          * of the open file structure, use them, otherwise allocate
  901          * additional memory for the number of descriptors currently
  902          * in use.
  903          */
  904         if (newfdp->fd_lastfile < NDFILE) {
  905                 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
  906                 newfdp->fd_ofileflags =
  907                     ((struct filedesc0 *) newfdp)->fd_dfileflags;
  908                 i = NDFILE;
  909         } else {
  910                 /*
  911                  * Compute the smallest multiple of NDEXTENT needed
  912                  * for the file descriptors currently in use,
  913                  * allowing the table to shrink.
  914                  */
  915                 i = newfdp->fd_nfiles;
  916                 while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
  917                         i /= 2;
  918                 newfdp->fd_ofiles = malloc(i * OFILESIZE, M_FILEDESC, M_WAITOK);
  919                 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
  920         }
  921         if (NDHISLOTS(i) <= NDHISLOTS(NDFILE)) {
  922                 newfdp->fd_himap =
  923                         ((struct filedesc0 *) newfdp)->fd_dhimap;
  924                 newfdp->fd_lomap =
  925                         ((struct filedesc0 *) newfdp)->fd_dlomap;
  926         } else {
  927                 newfdp->fd_himap = malloc(NDHISLOTS(i) * sizeof(u_int),
  928                     M_FILEDESC, M_WAITOK);
  929                 newfdp->fd_lomap = malloc(NDLOSLOTS(i) * sizeof(u_int),
  930                     M_FILEDESC, M_WAITOK);
  931         }
  932         newfdp->fd_nfiles = i;
  933         bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
  934         bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
  935         bcopy(fdp->fd_himap, newfdp->fd_himap, NDHISLOTS(i) * sizeof(u_int));
  936         bcopy(fdp->fd_lomap, newfdp->fd_lomap, NDLOSLOTS(i) * sizeof(u_int));
  937 
  938         /*
  939          * kq descriptors cannot be copied.
  940          */
  941         if (newfdp->fd_knlistsize != -1) {
  942                 fpp = newfdp->fd_ofiles;
  943                 for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
  944                         if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
  945                                 fdremove(newfdp, i);
  946                 newfdp->fd_knlist = NULL;
  947                 newfdp->fd_knlistsize = -1;
  948                 newfdp->fd_knhash = NULL;
  949                 newfdp->fd_knhashmask = 0;
  950         }
  951 
  952         fpp = newfdp->fd_ofiles;
  953         for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
  954                 if (*fpp != NULL) {
  955                         /*
  956                          * XXX Gruesome hack. If count gets too high, fail
  957                          * to copy an fd, since fdcopy()'s callers do not
  958                          * permit it to indicate failure yet.
  959                          */
  960                         if ((*fpp)->f_count == LONG_MAX-2)
  961                                 fdremove(newfdp, i);
  962                         else
  963                                 (*fpp)->f_count++;
  964                 }
  965         return (newfdp);
  966 }
  967 
  968 /*
  969  * Release a filedesc structure.
  970  */
  971 void
  972 fdfree(struct proc *p)
  973 {
  974         struct filedesc *fdp = p->p_fd;
  975         struct file **fpp, *fp;
  976         int i;
  977 
  978         if (--fdp->fd_refcnt > 0)
  979                 return;
  980         fpp = fdp->fd_ofiles;
  981         for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
  982                 fp = *fpp;
  983                 if (fp != NULL) {
  984                         FREF(fp);
  985                         *fpp = NULL;
  986                         (void) closef(fp, p);
  987                 }
  988         }
  989         p->p_fd = NULL;
  990         if (fdp->fd_nfiles > NDFILE)
  991                 free(fdp->fd_ofiles, M_FILEDESC);
  992         if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
  993                 free(fdp->fd_himap, M_FILEDESC);
  994                 free(fdp->fd_lomap, M_FILEDESC);
  995         }
  996         if (fdp->fd_cdir)
  997                 vrele(fdp->fd_cdir);
  998         if (fdp->fd_rdir)
  999                 vrele(fdp->fd_rdir);
 1000         if (fdp->fd_knlist)
 1001                 FREE(fdp->fd_knlist, M_TEMP);
 1002         if (fdp->fd_knhash)
 1003                 FREE(fdp->fd_knhash, M_TEMP);
 1004         pool_put(&fdesc_pool, fdp);
 1005 }
 1006 
 1007 /*
 1008  * Internal form of close.
 1009  * Decrement reference count on file structure.
 1010  * Note: p may be NULL when closing a file
 1011  * that was being passed in a message.
 1012  *
 1013  * The fp must have its usecount bumped and will be FRELEd here.
 1014  */
 1015 int
 1016 closef(struct file *fp, struct proc *p)
 1017 {
 1018         struct vnode *vp;
 1019         struct flock lf;
 1020         int error;
 1021 
 1022         if (fp == NULL)
 1023                 return (0);
 1024 
 1025         /*
 1026          * POSIX record locking dictates that any close releases ALL
 1027          * locks owned by this process.  This is handled by setting
 1028          * a flag in the unlock to free ONLY locks obeying POSIX
 1029          * semantics, and not to free BSD-style file locks.
 1030          * If the descriptor was in a message, POSIX-style locks
 1031          * aren't passed with the descriptor.
 1032          */
 1033         if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
 1034                 lf.l_whence = SEEK_SET;
 1035                 lf.l_start = 0;
 1036                 lf.l_len = 0;
 1037                 lf.l_type = F_UNLCK;
 1038                 vp = (struct vnode *)fp->f_data;
 1039                 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
 1040         }
 1041 
 1042         /*
 1043          * Some files passed to this function could be accessed
 1044          * without a FILE_IS_USABLE check (and in some cases it's perfectly
 1045          * legal), we must beware of files where someone already won the
 1046          * race to FIF_WANTCLOSE.
 1047          */
 1048         if ((fp->f_iflags & FIF_WANTCLOSE) != 0) {
 1049                 FRELE(fp);
 1050                 return (0);
 1051         }
 1052 
 1053         if (--fp->f_count > 0) {
 1054                 FRELE(fp);
 1055                 return (0);
 1056         }
 1057 
 1058 #ifdef DIAGNOSTIC
 1059         if (fp->f_count < 0)
 1060                 panic("closef: count < 0");
 1061 #endif
 1062 
 1063         /* Wait for the last usecount to drain. */
 1064         fp->f_iflags |= FIF_WANTCLOSE;
 1065         while (fp->f_usecount > 1)
 1066                 tsleep(&fp->f_usecount, PRIBIO, "closef", 0);
 1067 
 1068         if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
 1069                 lf.l_whence = SEEK_SET;
 1070                 lf.l_start = 0;
 1071                 lf.l_len = 0;
 1072                 lf.l_type = F_UNLCK;
 1073                 vp = (struct vnode *)fp->f_data;
 1074                 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
 1075         }
 1076         if (fp->f_ops)
 1077                 error = (*fp->f_ops->fo_close)(fp, p);
 1078         else
 1079                 error = 0;
 1080 
 1081         /* Free fp */
 1082         LIST_REMOVE(fp, f_list);
 1083         crfree(fp->f_cred);
 1084 #ifdef DIAGNOSTIC
 1085         if (fp->f_count != 0 || fp->f_usecount != 1)
 1086                 panic("closef: count: %d/%d", fp->f_count, fp->f_usecount);
 1087 #endif
 1088         nfiles--;
 1089         pool_put(&file_pool, fp);
 1090 
 1091         return (error);
 1092 }
 1093 
 1094 /*
 1095  * Apply an advisory lock on a file descriptor.
 1096  *
 1097  * Just attempt to get a record lock of the requested type on
 1098  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
 1099  */
 1100 /* ARGSUSED */
 1101 int
 1102 sys_flock(struct proc *p, void *v, register_t *retval)
 1103 {
 1104         struct sys_flock_args /* {
 1105                 syscallarg(int) fd;
 1106                 syscallarg(int) how;
 1107         } */ *uap = v;
 1108         int fd = SCARG(uap, fd);
 1109         int how = SCARG(uap, how);
 1110         struct filedesc *fdp = p->p_fd;
 1111         struct file *fp;
 1112         struct vnode *vp;
 1113         struct flock lf;
 1114         int error;
 1115 
 1116         if ((fp = fd_getfile(fdp, fd)) == NULL)
 1117                 return (EBADF);
 1118         if (fp->f_type != DTYPE_VNODE)
 1119                 return (EOPNOTSUPP);
 1120         vp = (struct vnode *)fp->f_data;
 1121         lf.l_whence = SEEK_SET;
 1122         lf.l_start = 0;
 1123         lf.l_len = 0;
 1124         if (how & LOCK_UN) {
 1125                 lf.l_type = F_UNLCK;
 1126                 fp->f_flag &= ~FHASLOCK;
 1127                 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
 1128                 goto out;
 1129         }
 1130         if (how & LOCK_EX)
 1131                 lf.l_type = F_WRLCK;
 1132         else if (how & LOCK_SH)
 1133                 lf.l_type = F_RDLCK;
 1134         else {
 1135                 error = EINVAL;
 1136                 goto out;
 1137         }
 1138         fp->f_flag |= FHASLOCK;
 1139         if (how & LOCK_NB)
 1140                 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK);
 1141         else
 1142                 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT);
 1143 out:
 1144         return (error);
 1145 }
 1146 
 1147 /*
 1148  * File Descriptor pseudo-device driver (/dev/fd/).
 1149  *
 1150  * Opening minor device N dup()s the file (if any) connected to file
 1151  * descriptor N belonging to the calling process.  Note that this driver
 1152  * consists of only the ``open()'' routine, because all subsequent
 1153  * references to this file will be direct to the other driver.
 1154  */
 1155 /* ARGSUSED */
 1156 int
 1157 filedescopen(dev_t dev, int mode, int type, struct proc *p)
 1158 {
 1159 
 1160         /*
 1161          * XXX Kludge: set curproc->p_dupfd to contain the value of the
 1162          * the file descriptor being sought for duplication. The error
 1163          * return ensures that the vnode for this device will be released
 1164          * by vn_open. Open will detect this special error and take the
 1165          * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
 1166          * will simply report the error.
 1167          */
 1168         p->p_dupfd = minor(dev);
 1169         return (ENODEV);
 1170 }
 1171 
 1172 /*
 1173  * Duplicate the specified descriptor to a free descriptor.
 1174  */
 1175 int
 1176 dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode, int error)
 1177 {
 1178         struct file *wfp;
 1179 
 1180         /*
 1181          * Assume that the filename was user-specified; applications do
 1182          * not tend to open /dev/fd/# when they can just call dup()
 1183          */
 1184         if ((curproc->p_flag & (P_SUGIDEXEC | P_SUGID))) {
 1185                 if (curproc->p_descfd == 255)
 1186                         return (EPERM);
 1187                 if (curproc->p_descfd != curproc->p_dupfd)
 1188                         return (EPERM);
 1189         }
 1190 
 1191         /*
 1192          * If the to-be-dup'd fd number is greater than the allowed number
 1193          * of file descriptors, or the fd to be dup'd has already been
 1194          * closed, reject. Note, there is no need to check for new == old
 1195          * because fd_getfile will return NULL if the file at indx is
 1196          * newly created by falloc (FIF_LARVAL).
 1197          */
 1198         if ((wfp = fd_getfile(fdp, dfd)) == NULL)
 1199                 return (EBADF);
 1200 
 1201         /*
 1202          * There are two cases of interest here.
 1203          *
 1204          * For ENODEV simply dup (dfd) to file descriptor
 1205          * (indx) and return.
 1206          *
 1207          * For ENXIO steal away the file structure from (dfd) and
 1208          * store it in (indx).  (dfd) is effectively closed by
 1209          * this operation.
 1210          *
 1211          * Any other error code is just returned.
 1212          */
 1213         switch (error) {
 1214         case ENODEV:
 1215                 /*
 1216                  * Check that the mode the file is being opened for is a
 1217                  * subset of the mode of the existing descriptor.
 1218                  */
 1219                 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
 1220                         return (EACCES);
 1221                 if (wfp->f_count == LONG_MAX-2)
 1222                         return (EDEADLK);
 1223                 fdp->fd_ofiles[indx] = wfp;
 1224                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 1225                 wfp->f_count++;
 1226                 fd_used(fdp, indx);
 1227                 return (0);
 1228 
 1229         case ENXIO:
 1230                 /*
 1231                  * Steal away the file pointer from dfd, and stuff it into indx.
 1232                  */
 1233                 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
 1234                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 1235                 fdp->fd_ofiles[dfd] = NULL;
 1236                 fdp->fd_ofileflags[dfd] = 0;
 1237                 /*
 1238                  * Complete the clean up of the filedesc structure by
 1239                  * recomputing the various hints.
 1240                  */
 1241                 fd_used(fdp, indx);
 1242                 fd_unused(fdp, dfd);
 1243                 return (0);
 1244 
 1245         default:
 1246                 return (error);
 1247         }
 1248         /* NOTREACHED */
 1249 }
 1250 
 1251 /*
 1252  * Close any files on exec?
 1253  */
 1254 void
 1255 fdcloseexec(struct proc *p)
 1256 {
 1257         struct filedesc *fdp = p->p_fd;
 1258         int fd;
 1259 
 1260         for (fd = 0; fd <= fdp->fd_lastfile; fd++)
 1261                 if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
 1262                         (void) fdrelease(p, fd);
 1263 }
 1264 
 1265 int
 1266 sys_closefrom(struct proc *p, void *v, register_t *retval)
 1267 {
 1268         struct sys_closefrom_args *uap = v;
 1269         struct filedesc *fdp = p->p_fd;
 1270         u_int startfd, i;
 1271 
 1272         startfd = SCARG(uap, fd);
 1273         fdplock(fdp);
 1274 
 1275         if (startfd > fdp->fd_lastfile) {
 1276                 fdpunlock(fdp);
 1277                 return (EBADF);
 1278         }
 1279 
 1280         for (i = startfd; i <= fdp->fd_lastfile; i++)
 1281                 fdrelease(p, i);
 1282 
 1283         fdpunlock(fdp);
 1284         return (0);
 1285 }

/* [<][>][^][v][top][bottom][index][help] */