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/bsd/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) 2000-2004 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * The contents of this file constitute Original Code as defined in and
    7  * are subject to the Apple Public Source License Version 1.1 (the
    8  * "License").  You may not use this file except in compliance with the
    9  * License.  Please obtain a copy of the License at
   10  * http://www.apple.com/publicsource and read it before using this file.
   11  * 
   12  * This Original Code and all software distributed under the License are
   13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
   17  * License for the specific language governing rights and limitations
   18  * under the License.
   19  * 
   20  * @APPLE_LICENSE_HEADER_END@
   21  */
   22 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
   23 /*
   24  * Copyright (c) 1982, 1986, 1989, 1991, 1993
   25  *      The Regents of the University of California.  All rights reserved.
   26  * (c) UNIX System Laboratories, Inc.
   27  * All or some portions of this file are derived from material licensed
   28  * to the University of California by American Telephone and Telegraph
   29  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   30  * the permission of UNIX System Laboratories, Inc.
   31  *
   32  * Redistribution and use in source and binary forms, with or without
   33  * modification, are permitted provided that the following conditions
   34  * are met:
   35  * 1. Redistributions of source code must retain the above copyright
   36  *    notice, this list of conditions and the following disclaimer.
   37  * 2. Redistributions in binary form must reproduce the above copyright
   38  *    notice, this list of conditions and the following disclaimer in the
   39  *    documentation and/or other materials provided with the distribution.
   40  * 3. All advertising materials mentioning features or use of this software
   41  *    must display the following acknowledgement:
   42  *      This product includes software developed by the University of
   43  *      California, Berkeley and its contributors.
   44  * 4. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)kern_descrip.c      8.8 (Berkeley) 2/14/95
   61  */
   62 
   63 #include <sys/param.h>
   64 #include <sys/systm.h>
   65 #include <sys/filedesc.h>
   66 #include <sys/kernel.h>
   67 #include <sys/vnode_internal.h>
   68 #include <sys/proc_internal.h>
   69 #include <sys/kauth.h>
   70 #include <sys/file_internal.h>
   71 #include <sys/socket.h>
   72 #include <sys/socketvar.h>
   73 #include <sys/stat.h>
   74 #include <sys/ioctl.h>
   75 #include <sys/fcntl.h>
   76 #include <sys/malloc.h>
   77 #include <sys/mman.h>
   78 #include <sys/syslog.h>
   79 #include <sys/unistd.h>
   80 #include <sys/resourcevar.h>
   81 #include <sys/aio_kern.h>
   82 #include <sys/ev.h>
   83 #include <kern/lock.h>
   84 
   85 #include <bsm/audit_kernel.h>
   86 
   87 #include <sys/mount_internal.h>
   88 #include <sys/kdebug.h>
   89 #include <sys/sysproto.h>
   90 #include <sys/pipe.h>
   91 #include <kern/kern_types.h>
   92 #include <kern/kalloc.h>
   93 
   94 struct psemnode;
   95 struct pshmnode;
   96 
   97 int fdopen(dev_t dev, int mode, int type, struct proc *p);
   98 int ogetdtablesize(struct proc *p, void *uap, register_t *retval);
   99 int finishdup(struct proc * p, struct filedesc *fdp, int old, int new, register_t *retval);
  100 
  101 int closef(struct fileglob *fg, struct proc *p);
  102 int falloc_locked(struct proc *p, struct fileproc **resultfp, int *resultfd, int locked);
  103 void fddrop(struct proc *p, int fd);
  104 int fdgetf_noref(struct proc *p, int fd, struct fileproc **resultfp);
  105 void fg_drop(struct fileproc * fp);
  106 void fg_free(struct fileglob *fg);
  107 void fg_ref(struct fileproc * fp);
  108 int fp_getfpshm(struct proc *p, int fd, struct fileproc **resultfp, struct pshmnode  **resultpshm);
  109 
  110 static int closef_finish(struct fileproc *fp, struct fileglob *fg, struct proc *p);
  111 
  112 extern void file_lock_init(void);
  113 extern int is_suser(void);
  114 extern int kqueue_stat(struct fileproc *fp, struct stat *st, struct proc *p);
  115 extern int soo_stat(struct socket *so, struct stat *ub);
  116 extern int vn_path_package_check(vnode_t vp, char *path, int pathlen, int *component);
  117 
  118 extern kauth_scope_t    kauth_scope_fileop;
  119 
  120 #define f_flag f_fglob->fg_flag
  121 #define f_type f_fglob->fg_type
  122 #define f_msgcount f_fglob->fg_msgcount
  123 #define f_cred f_fglob->fg_cred
  124 #define f_ops f_fglob->fg_ops
  125 #define f_offset f_fglob->fg_offset
  126 #define f_data f_fglob->fg_data
  127 /*
  128  * Descriptor management.
  129  */
  130 struct filelist filehead;       /* head of list of open files */
  131 struct fmsglist fmsghead;       /* head of list of open files */
  132 struct fmsglist fmsg_ithead;    /* head of list of open files */
  133 int nfiles;                     /* actual number of open files */
  134 
  135 
  136 lck_grp_attr_t * file_lck_grp_attr;
  137 lck_grp_t * file_lck_grp;
  138 lck_attr_t * file_lck_attr;
  139 
  140 lck_mtx_t * uipc_lock;
  141 lck_mtx_t * file_iterate_lcok;
  142 lck_mtx_t * file_flist_lock;
  143 
  144 
  145 void
  146 file_lock_init(void)
  147 {
  148 
  149         /* allocate file lock group attribute and group */
  150         file_lck_grp_attr= lck_grp_attr_alloc_init();
  151         lck_grp_attr_setstat(file_lck_grp_attr);
  152 
  153         file_lck_grp = lck_grp_alloc_init("file",  file_lck_grp_attr);
  154 
  155         /* Allocate file lock attribute */
  156         file_lck_attr = lck_attr_alloc_init();
  157         //lck_attr_setdebug(file_lck_attr);
  158 
  159         uipc_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
  160         file_iterate_lcok = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
  161         file_flist_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
  162 
  163         
  164 
  165 }
  166 
  167 
  168 void
  169 proc_fdlock(struct proc *p)
  170 {
  171         lck_mtx_lock(&p->p_fdmlock);
  172 }
  173 
  174 void
  175 proc_fdunlock(struct proc *p)
  176 {
  177         lck_mtx_unlock(&p->p_fdmlock);
  178 }
  179 
  180 /*
  181  * System calls on descriptors.
  182  */
  183 
  184 int
  185 getdtablesize(struct proc *p, __unused struct getdtablesize_args *uap, register_t *retval)
  186 {
  187         proc_fdlock(p);
  188         *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
  189         proc_fdunlock(p);
  190 
  191         return (0);
  192 }
  193 
  194 int
  195 ogetdtablesize(struct proc *p, __unused void *uap, register_t *retval)
  196 {
  197         proc_fdlock(p);
  198         *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, NOFILE);
  199         proc_fdunlock(p);
  200 
  201         return (0);
  202 }
  203 
  204 static __inline__ void
  205 _fdrelse(struct filedesc *fdp, int fd)
  206 {
  207         if (fd < fdp->fd_freefile)
  208                 fdp->fd_freefile = fd;
  209 #if DIAGNOSTIC
  210         if (fd > fdp->fd_lastfile)
  211                 panic("fdrelse: fd_lastfile inconsistent");
  212 #endif
  213         fdp->fd_ofiles[fd] = NULL;
  214         fdp->fd_ofileflags[fd] = 0;
  215 
  216         while ((fd = fdp->fd_lastfile) > 0 &&
  217                         fdp->fd_ofiles[fd] == NULL &&
  218                         !(fdp->fd_ofileflags[fd] & UF_RESERVED))
  219                 fdp->fd_lastfile--;
  220 }
  221 
  222 /*
  223  * Duplicate a file descriptor.
  224  */
  225 /* ARGSUSED */
  226 int
  227 dup(p, uap, retval)
  228         struct proc *p;
  229         struct dup_args *uap;
  230         register_t *retval;
  231 {
  232         register struct filedesc *fdp = p->p_fd;
  233         register int old = uap->fd;
  234         int new, error;
  235         struct fileproc *fp;
  236 
  237         proc_fdlock(p);
  238         if ( (error = fp_lookup(p, old, &fp, 1)) ) {
  239                 proc_fdunlock(p);
  240                 return(error);
  241         }
  242         if ( (error = fdalloc(p, 0, &new)) ) {
  243                 fp_drop(p, old, fp, 1);
  244                 proc_fdunlock(p);
  245                 return (error);
  246         }
  247         error = finishdup(p, fdp, old, new, retval);
  248         fp_drop(p, old, fp, 1);
  249         proc_fdunlock(p);
  250 
  251         return (error);
  252 }
  253 
  254 /*
  255  * Duplicate a file descriptor to a particular value.
  256  */
  257 /* ARGSUSED */
  258 int
  259 dup2(p, uap, retval)
  260         struct proc *p;
  261         struct dup2_args *uap;
  262         register_t *retval;
  263 {
  264         register struct filedesc *fdp = p->p_fd;
  265         register int old = uap->from, new = uap->to;
  266         int i, error;
  267         struct fileproc *fp;
  268 
  269         proc_fdlock(p);
  270 
  271         if ( (error = fp_lookup(p, old, &fp, 1)) ) {
  272                 proc_fdunlock(p);
  273                 return(error);
  274         }
  275         if (new < 0 ||
  276                 new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  277             new >= maxfiles) {
  278                 fp_drop(p, old, fp, 1);
  279                 proc_fdunlock(p);
  280                 return (EBADF);
  281         }
  282         if (old == new) {
  283                 fp_drop(p, old, fp, 1);
  284                 *retval = new;
  285                 proc_fdunlock(p);
  286                 return (0);
  287         }
  288         if (new < 0 || new >= fdp->fd_nfiles) {
  289                 if ( (error = fdalloc(p, new, &i)) ) {
  290                         fp_drop(p, old, fp, 1);
  291                         proc_fdunlock(p);
  292                         return (error);
  293                 }
  294                 if (new != i) {
  295                         _fdrelse(fdp, i);
  296                         goto closeit;
  297                 }
  298         } else {
  299                 struct fileproc **fpp;
  300                 char flags;
  301 closeit:
  302                 flags = fdp->fd_ofileflags[new];
  303                 if ((flags & (UF_RESERVED | UF_CLOSING)) == UF_RESERVED) {
  304                         fp_drop(p, old, fp, 1);
  305                         proc_fdunlock(p);
  306                         return (EBADF);
  307                 }
  308 
  309                 /*
  310                  * dup2() must succeed even if the close has an error.
  311                  */
  312                 if (*(fpp = &fdp->fd_ofiles[new])) {
  313                         struct fileproc *nfp = *fpp;
  314 
  315                         close_internal(p, new, nfp, (CLOSEINT_LOCKED | CLOSEINT_WAITONCLOSE | CLOSEINT_NOFDRELSE | CLOSEINT_NOFDNOREF));
  316                         *fpp = NULL;
  317                 }
  318         }
  319         error = finishdup(p, fdp, old, new, retval);
  320         fp_drop(p, old, fp, 1);
  321         proc_fdunlock(p);
  322 
  323         return(error);
  324 }
  325 
  326 /*
  327  * The file control system call.
  328  */
  329 int
  330 fcntl(p, uap, retval)
  331         struct proc *p;
  332         struct fcntl_args *uap;
  333         register_t *retval;
  334 {
  335         int fd = uap->fd;
  336         struct filedesc *fdp = p->p_fd;
  337         struct fileproc *fp;
  338         char *pop;
  339         struct vnode *vp;
  340         int i, tmp, error, error2, flg = F_POSIX;
  341         struct flock fl;
  342         struct vfs_context context;
  343         off_t offset;
  344         int newmin;
  345         daddr64_t lbn, bn;
  346         int devBlockSize = 0;
  347         unsigned int fflag;
  348         user_addr_t argp;
  349 
  350         AUDIT_ARG(fd, uap->fd);
  351         AUDIT_ARG(cmd, uap->cmd);
  352 
  353         proc_fdlock(p);
  354         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
  355                 proc_fdunlock(p);
  356                 return(error);
  357         }
  358         context.vc_proc = p;
  359         context.vc_ucred = fp->f_cred;
  360         if (proc_is64bit(p)) {
  361                 argp = uap->arg;
  362         }
  363         else {
  364                 /* since the arg parameter is defined as a long but may be either
  365                  * a long or a pointer we must take care to handle sign extension 
  366                  * issues.  Our sys call munger will sign extend a long when we are
  367                  * called from a 32-bit process.  Since we can never have an address
  368                  * greater than 32-bits from a 32-bit process we lop off the top 
  369                  * 32-bits to avoid getting the wrong address
  370                  */
  371                 argp = CAST_USER_ADDR_T(uap->arg);
  372         }
  373 
  374         pop = &fdp->fd_ofileflags[fd];
  375 
  376         switch (uap->cmd) {
  377 
  378         case F_DUPFD:
  379                 newmin = CAST_DOWN(int, uap->arg);
  380                 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  381                     newmin >= maxfiles) {
  382                         error = EINVAL;
  383                         goto out;
  384                 }
  385                 if ( (error = fdalloc(p, newmin, &i)) )
  386                         goto out;
  387                 error = finishdup(p, fdp, fd, i, retval);
  388                 goto out;
  389 
  390         case F_GETFD:
  391                 *retval = (*pop & UF_EXCLOSE)? 1 : 0;
  392                 error = 0;
  393                 goto out;
  394 
  395         case F_SETFD:
  396                 *pop = (*pop &~ UF_EXCLOSE) |
  397                         (uap->arg & 1)? UF_EXCLOSE : 0;
  398                 error = 0;
  399                 goto out;
  400 
  401         case F_GETFL:
  402                 *retval = OFLAGS(fp->f_flag);
  403                 error = 0;
  404                 goto out;
  405 
  406         case F_SETFL:
  407                 fp->f_flag &= ~FCNTLFLAGS;
  408                 tmp = CAST_DOWN(int, uap->arg);
  409                 fp->f_flag |= FFLAGS(tmp) & FCNTLFLAGS;
  410                 tmp = fp->f_flag & FNONBLOCK;
  411                 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
  412                 if (error)
  413                         goto out;
  414                 tmp = fp->f_flag & FASYNC;
  415                 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
  416                 if (!error)
  417                         goto out;
  418                 fp->f_flag &= ~FNONBLOCK;
  419                 tmp = 0;
  420                 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
  421                 goto out;
  422 
  423         case F_GETOWN:
  424                 if (fp->f_type == DTYPE_SOCKET) {
  425                         *retval = ((struct socket *)fp->f_data)->so_pgid;
  426                         error = 0;
  427                         goto out;
  428                 }
  429                 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
  430                 *retval = -*retval;
  431                 goto out;
  432 
  433         case F_SETOWN:
  434                 tmp = CAST_DOWN(pid_t, uap->arg);
  435                 if (fp->f_type == DTYPE_SOCKET) {
  436                         ((struct socket *)fp->f_data)->so_pgid = tmp;
  437                         error =0;
  438                         goto out;
  439                 }
  440                 if (fp->f_type == DTYPE_PIPE) {
  441                         error =  fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
  442                         goto out;
  443                 }
  444 
  445                 if (tmp <= 0) {
  446                         tmp = -tmp;
  447                 } else {
  448                         struct proc *p1 = pfind(tmp);
  449                         if (p1 == 0) {
  450                                 error = ESRCH;
  451                                 goto out;
  452                         }
  453                         tmp = (int)p1->p_pgrp->pg_id;
  454                 }
  455                 error =  fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
  456                 goto out;
  457 
  458         case F_SETLKW:
  459                 flg |= F_WAIT;
  460                 /* Fall into F_SETLK */
  461 
  462         case F_SETLK:
  463                 if (fp->f_type != DTYPE_VNODE) {
  464                         error = EBADF;
  465                         goto out;
  466                 }
  467                 vp = (struct vnode *)fp->f_data;
  468 
  469                 fflag = fp->f_flag;
  470                 offset = fp->f_offset;
  471                 proc_fdunlock(p);
  472 
  473                 /* Copy in the lock structure */
  474                 error = copyin(argp, (caddr_t)&fl, sizeof (fl));
  475                 if (error) {
  476                         goto outdrop;
  477                 }
  478                 if ( (error = vnode_getwithref(vp)) ) {
  479                         goto outdrop;
  480                 }
  481                 if (fl.l_whence == SEEK_CUR)
  482                         fl.l_start += offset;
  483 
  484                 switch (fl.l_type) {
  485 
  486                 case F_RDLCK:
  487                         if ((fflag & FREAD) == 0) {
  488                                 (void)vnode_put(vp);
  489                                 error = EBADF;
  490                                 goto outdrop;
  491                         }
  492                         p->p_flag |= P_ADVLOCK;
  493                         error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
  494                         (void)vnode_put(vp);
  495                         goto outdrop;
  496 
  497                 case F_WRLCK:
  498                         if ((fflag & FWRITE) == 0) {
  499                                 (void)vnode_put(vp);
  500                                 error = EBADF;
  501                                 goto outdrop;
  502                         }
  503                         p->p_flag |= P_ADVLOCK;
  504                         error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
  505                         (void)vnode_put(vp);
  506                         goto outdrop;
  507 
  508                 case F_UNLCK:
  509                         error = VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
  510                                 F_POSIX, &context);
  511                         (void)vnode_put(vp);
  512                         goto outdrop;
  513 
  514                 default:
  515                         (void)vnode_put(vp);
  516                         error = EINVAL;
  517                         goto outdrop;
  518                 }
  519 
  520         case F_GETLK:
  521                 if (fp->f_type != DTYPE_VNODE) {
  522                         error = EBADF;
  523                         goto out;
  524                 }
  525                 vp = (struct vnode *)fp->f_data;
  526 
  527                 offset = fp->f_offset;
  528                 proc_fdunlock(p);
  529 
  530                 /* Copy in the lock structure */
  531                 error = copyin(argp, (caddr_t)&fl, sizeof (fl));
  532                 if (error)
  533                         goto outdrop;
  534 
  535                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  536                         if (fl.l_whence == SEEK_CUR)
  537                                 fl.l_start += offset;
  538 
  539                         error = VNOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX, &context);
  540 
  541                         (void)vnode_put(vp);
  542 
  543                         if (error == 0)
  544                                 error = copyout((caddr_t)&fl, argp, sizeof (fl));
  545                 }
  546                 goto outdrop;
  547 
  548         case F_PREALLOCATE: {
  549                 fstore_t alloc_struct;    /* structure for allocate command */
  550                 u_int32_t alloc_flags = 0;
  551 
  552                 if (fp->f_type != DTYPE_VNODE) {
  553                         error = EBADF;
  554                         goto out;
  555                 }
  556 
  557                 vp = (struct vnode *)fp->f_data;
  558                 proc_fdunlock(p);
  559 
  560                 /* make sure that we have write permission */
  561                 if ((fp->f_flag & FWRITE) == 0) {
  562                         error = EBADF;
  563                         goto outdrop;
  564                 }
  565 
  566                 error = copyin(argp, (caddr_t)&alloc_struct, sizeof (alloc_struct));
  567                 if (error)
  568                         goto outdrop;
  569 
  570                 /* now set the space allocated to 0 */
  571                 alloc_struct.fst_bytesalloc = 0;
  572                 
  573                 /*
  574                  * Do some simple parameter checking
  575                  */
  576 
  577                 /* set up the flags */
  578 
  579                 alloc_flags |= PREALLOCATE;
  580                 
  581                 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
  582                         alloc_flags |= ALLOCATECONTIG;
  583 
  584                 if (alloc_struct.fst_flags & F_ALLOCATEALL)
  585                         alloc_flags |= ALLOCATEALL;
  586 
  587                 /*
  588                  * Do any position mode specific stuff.  The only
  589                  * position mode  supported now is PEOFPOSMODE
  590                  */
  591 
  592                 switch (alloc_struct.fst_posmode) {
  593         
  594                 case F_PEOFPOSMODE:
  595                         if (alloc_struct.fst_offset != 0) {
  596                                 error = EINVAL;
  597                                 goto outdrop;
  598                         }
  599 
  600                         alloc_flags |= ALLOCATEFROMPEOF;
  601                         break;
  602 
  603                 case F_VOLPOSMODE:
  604                         if (alloc_struct.fst_offset <= 0) {
  605                                 error = EINVAL;
  606                                 goto outdrop;
  607                         }
  608 
  609                         alloc_flags |= ALLOCATEFROMVOL;
  610                         break;
  611 
  612                 default: {
  613                         error = EINVAL;
  614                         goto outdrop;
  615                         }
  616                 }
  617                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  618                         /*
  619                          * call allocate to get the space
  620                          */
  621                         error = VNOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
  622                                               &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
  623                                               &context);
  624                         (void)vnode_put(vp);
  625 
  626                         error2 = copyout((caddr_t)&alloc_struct, argp, sizeof (alloc_struct));
  627 
  628                         if (error == 0)
  629                                 error = error2;
  630                 }
  631                 goto outdrop;
  632                 
  633                 }
  634         case F_SETSIZE:
  635                 if (fp->f_type != DTYPE_VNODE) {
  636                         error = EBADF;
  637                         goto out;
  638                 }
  639                 proc_fdunlock(p);
  640 
  641                 error = copyin(argp, (caddr_t)&offset, sizeof (off_t));
  642                 if (error)
  643                         goto outdrop;
  644 
  645                 /*
  646                  * Make sure that we are root.  Growing a file
  647                  * without zero filling the data is a security hole 
  648                  * root would have access anyway so we'll allow it
  649                  */
  650 
  651                 if (!is_suser()) {
  652                         error = EACCES;
  653                         goto outdrop;
  654                 }
  655                 vp = (struct vnode *)fp->f_data;
  656 
  657                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  658                         /*
  659                          * set the file size
  660                          */
  661                         error = vnode_setsize(vp, offset, IO_NOZEROFILL, &context);
  662 
  663                         (void)vnode_put(vp);
  664                 }
  665                 goto outdrop;
  666 
  667         case F_RDAHEAD:
  668                 if (fp->f_type != DTYPE_VNODE) {
  669                         error = EBADF;
  670                         goto out;
  671                 }
  672                 vp = (struct vnode *)fp->f_data;
  673                 proc_fdunlock(p);
  674 
  675                 if ( (error = vnode_getwithref(vp)) == 0) {
  676                         if (uap->arg)
  677                                 vnode_clearnoreadahead(vp);
  678                         else
  679                                 vnode_setnoreadahead(vp);
  680 
  681                         (void)vnode_put(vp);
  682                 }
  683                 goto outdrop;
  684 
  685         case F_NOCACHE:
  686                 if (fp->f_type != DTYPE_VNODE) {
  687                         error = EBADF;
  688                         goto out;
  689                 }
  690                 vp = (struct vnode *)fp->f_data;
  691                 proc_fdunlock(p);
  692 
  693                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  694                         if (uap->arg)
  695                                 vnode_setnocache(vp);
  696                         else
  697                                 vnode_clearnocache(vp);
  698 
  699                         (void)vnode_put(vp);
  700                 }
  701                 goto outdrop;
  702 
  703         case F_RDADVISE: {
  704                 struct radvisory ra_struct;
  705 
  706                 if (fp->f_type != DTYPE_VNODE) {
  707                         error = EBADF;
  708                         goto out;
  709                 }
  710                 vp = (struct vnode *)fp->f_data;
  711                 proc_fdunlock(p);
  712 
  713                 if ( (error = copyin(argp, (caddr_t)&ra_struct, sizeof (ra_struct))) )
  714                         goto outdrop;
  715                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  716                         error = VNOP_IOCTL(vp, F_RDADVISE, (caddr_t)&ra_struct, 0, &context);
  717 
  718                         (void)vnode_put(vp);
  719                 }
  720                 goto outdrop;
  721                 }
  722 
  723         case F_READBOOTSTRAP:
  724         case F_WRITEBOOTSTRAP: {
  725                 fbootstraptransfer_t fbt_struct;
  726                 user_fbootstraptransfer_t user_fbt_struct;
  727                 int     sizeof_struct;
  728                 caddr_t boot_structp;
  729 
  730                 if (fp->f_type != DTYPE_VNODE) {
  731                         error = EBADF;
  732                         goto out;
  733                 }
  734                 vp = (struct vnode *)fp->f_data;
  735                 proc_fdunlock(p);
  736 
  737                 if (IS_64BIT_PROCESS(p)) {
  738                         sizeof_struct = sizeof(user_fbt_struct);
  739                         boot_structp = (caddr_t) &user_fbt_struct;
  740                 }
  741                 else {
  742                         sizeof_struct = sizeof(fbt_struct);
  743                         boot_structp = (caddr_t) &fbt_struct;
  744                 }
  745                 error = copyin(argp, boot_structp, sizeof_struct);
  746                 if (error)
  747                         goto outdrop;
  748                 if ( (error = vnode_getwithref(vp)) ) {
  749                         goto outdrop;
  750                 }
  751                 if (uap->cmd == F_WRITEBOOTSTRAP) {
  752                         /*
  753                          * Make sure that we are root.  Updating the
  754                          * bootstrap on a disk could be a security hole
  755                          */
  756                         if (!is_suser()) {
  757                                 (void)vnode_put(vp);
  758                                 error = EACCES;
  759                                 goto outdrop;
  760                         }
  761                 }
  762                 if (strcmp(vnode_mount(vp)->mnt_vfsstat.f_fstypename, "hfs") != 0) {
  763                         error = EINVAL;
  764                 } else {
  765                         /*
  766                          * call vnop_ioctl to handle the I/O
  767                          */
  768                         error = VNOP_IOCTL(vp, uap->cmd, boot_structp, 0, &context);
  769                 }
  770                 (void)vnode_put(vp);
  771                 goto outdrop;
  772         }
  773         case F_LOG2PHYS: {
  774                 struct log2phys l2p_struct;    /* structure for allocate command */
  775 
  776                 if (fp->f_type != DTYPE_VNODE) {
  777                         error = EBADF;
  778                         goto out;
  779                 }
  780                 vp = (struct vnode *)fp->f_data;
  781                 proc_fdunlock(p);
  782                 if ( (error = vnode_getwithref(vp)) ) {
  783                         goto outdrop;
  784                 }
  785                 error = VNOP_OFFTOBLK(vp, fp->f_offset, &lbn);
  786                 if (error) {
  787                         (void)vnode_put(vp);
  788                         goto outdrop;
  789                 }
  790                 error = VNOP_BLKTOOFF(vp, lbn, &offset);
  791                 if (error) {
  792                         (void)vnode_put(vp);
  793                         goto outdrop;
  794                 }
  795                 devBlockSize = vfs_devblocksize(vnode_mount(vp));
  796 
  797                 error = VNOP_BLOCKMAP(vp, offset, devBlockSize, &bn, NULL, NULL, 0, &context);
  798 
  799                 (void)vnode_put(vp);
  800 
  801                 if (!error) {
  802                         l2p_struct.l2p_flags = 0;       /* for now */
  803                         l2p_struct.l2p_contigbytes = 0; /* for now */
  804                         l2p_struct.l2p_devoffset = bn * devBlockSize;
  805                         l2p_struct.l2p_devoffset += fp->f_offset - offset;
  806                         error = copyout((caddr_t)&l2p_struct, argp, sizeof (l2p_struct));
  807                 }
  808                 goto outdrop;
  809                 }
  810         case F_GETPATH: {
  811                 char *pathbufp;
  812                 int pathlen;
  813 
  814                 if (fp->f_type != DTYPE_VNODE) {
  815                         error = EBADF;
  816                         goto out;
  817                 }
  818                 vp = (struct vnode *)fp->f_data;
  819                 proc_fdunlock(p);
  820 
  821                 pathlen = MAXPATHLEN;
  822                 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
  823                 if (pathbufp == NULL) {
  824                         error = ENOMEM;
  825                         goto outdrop;
  826                 }
  827                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  828                         error = vn_getpath(vp, pathbufp, &pathlen);
  829                         (void)vnode_put(vp);
  830 
  831                         if (error == 0)
  832                                 error = copyout((caddr_t)pathbufp, argp, pathlen);
  833                 }
  834                 FREE(pathbufp, M_TEMP);
  835                 goto outdrop;
  836         }
  837 
  838         case F_PATHPKG_CHECK: {
  839                 char *pathbufp;
  840                 size_t pathlen;
  841 
  842                 if (fp->f_type != DTYPE_VNODE) {
  843                         error = EBADF;
  844                         goto out;
  845                 }
  846                 vp = (struct vnode *)fp->f_data;
  847                 proc_fdunlock(p);
  848 
  849                 pathlen = MAXPATHLEN;
  850                 pathbufp = kalloc(MAXPATHLEN);
  851 
  852                 if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
  853                         if ( (error = vnode_getwithref(vp)) == 0 ) {
  854                                 error = vn_path_package_check(vp, pathbufp, pathlen, retval);
  855 
  856                                 (void)vnode_put(vp);
  857                         }
  858                 }
  859                 kfree(pathbufp, MAXPATHLEN);
  860                 goto outdrop;
  861         }
  862 
  863         case F_CHKCLEAN:   // used by regression tests to see if all dirty pages got cleaned by fsync()
  864         case F_FULLFSYNC:  // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
  865         case F_FREEZE_FS:  // freeze all other fs operations for the fs of this fd
  866         case F_THAW_FS: {  // thaw all frozen fs operations for the fs of this fd
  867                 if (fp->f_type != DTYPE_VNODE) {
  868                         error = EBADF;
  869                         goto out;
  870                 }
  871                 vp = (struct vnode *)fp->f_data;
  872                 proc_fdunlock(p);
  873 
  874                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  875                         error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)NULL, 0, &context);
  876 
  877                         (void)vnode_put(vp);
  878                 }
  879                 break;
  880         }
  881             
  882         default:
  883                 if (uap->cmd < FCNTL_FS_SPECIFIC_BASE) {
  884                         error = EINVAL;
  885                         goto out;
  886                 }
  887 
  888                 // if it's a fs-specific fcntl() then just pass it through
  889 
  890                 if (fp->f_type != DTYPE_VNODE) {
  891                         error = EBADF;
  892                         goto out;
  893                 }
  894                 vp = (struct vnode *)fp->f_data;
  895                 proc_fdunlock(p);
  896 
  897                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  898                         error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, argp), 0, &context);
  899 
  900                         (void)vnode_put(vp);
  901                 }
  902                 break;
  903         
  904         }
  905 
  906 outdrop:
  907         AUDIT_ARG(vnpath_withref, vp, ARG_VNODE1);
  908         fp_drop(p, fd, fp, 0);
  909         return(error);
  910 out:
  911         fp_drop(p, fd, fp, 1);
  912         proc_fdunlock(p);
  913         return(error);
  914 }
  915 
  916 /*
  917  * Common code for dup, dup2, and fcntl(F_DUPFD).
  918  */
  919 int
  920 finishdup(struct proc * p, struct filedesc *fdp, int old, int new, register_t *retval)
  921 {
  922         struct fileproc *nfp;
  923         struct fileproc *ofp;
  924 
  925         if ((ofp = fdp->fd_ofiles[old]) == NULL ||
  926                         (fdp->fd_ofileflags[old] & UF_RESERVED)) {
  927                 _fdrelse(fdp, new);
  928                 return (EBADF);
  929         }
  930         fg_ref(ofp);
  931         proc_fdunlock(p);
  932 
  933         MALLOC_ZONE(nfp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
  934         bzero(nfp, sizeof(struct fileproc));
  935 
  936         proc_fdlock(p);
  937         nfp->f_flags = ofp->f_flags;
  938         nfp->f_fglob = ofp->f_fglob;
  939         nfp->f_iocount = 0;
  940 
  941         fdp->fd_ofiles[new] = nfp;
  942         fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
  943         if (new > fdp->fd_lastfile)
  944                 fdp->fd_lastfile = new;
  945         *retval = new;
  946         return (0);
  947 }
  948 
  949 
  950 int
  951 close(struct proc *p, struct close_args *uap, __unused register_t *retval)
  952 {
  953         struct fileproc *fp;
  954         int fd = uap->fd;
  955         int error =0;
  956 
  957         AUDIT_SYSCLOSE(p, fd);
  958 
  959         proc_fdlock(p);
  960 
  961         if ( (error = fp_lookup(p,fd,&fp, 1)) ) {
  962                 proc_fdunlock(p);
  963                 return(error);
  964         }
  965 
  966         error = close_internal(p, fd, fp, CLOSEINT_LOCKED | CLOSEINT_WAITONCLOSE);
  967 
  968         proc_fdunlock(p);
  969 
  970         return(error);
  971 }
  972 
  973 
  974 /*
  975  * Close a file descriptor.
  976  */
  977 int
  978 close_internal(struct proc *p, int fd, struct fileproc *fp, int flags)
  979 {
  980         struct filedesc *fdp = p->p_fd;
  981         int error =0;
  982         int locked = flags & CLOSEINT_LOCKED;
  983         int waitonclose = flags & CLOSEINT_WAITONCLOSE;
  984         int norelse = flags & CLOSEINT_NOFDRELSE;
  985         int nofdref = flags & CLOSEINT_NOFDNOREF;
  986         int slpstate = PRIBIO;
  987 
  988         if (!locked)
  989                 proc_fdlock(p);
  990 
  991         /* Keep people from using the filedesc while we are closing it */
  992         fdp->fd_ofileflags[fd] |= UF_RESERVED;
  993 
  994         fdp->fd_ofileflags[fd] |= UF_CLOSING;
  995 
  996 
  997         if ((waitonclose && ((fp->f_flags & FP_CLOSING) == FP_CLOSING))) {
  998                         if (nofdref == 0)
  999                                 fp_drop(p, fd, fp, 1);
 1000                         fp->f_flags |= FP_WAITCLOSE;
 1001                         if (!locked)
 1002                                 slpstate |= PDROP;
 1003                         msleep(&fp->f_flags, &p->p_fdmlock, slpstate, "close wait",0) ; 
 1004                         return(EBADF);
 1005         }
 1006 
 1007         fp->f_flags |= FP_CLOSING;
 1008         if (nofdref)
 1009                 fp->f_iocount++;
 1010 
 1011         if ( (fp->f_flags & FP_AIOISSUED) || kauth_authorize_fileop_has_listeners() ) {
 1012 
 1013                 proc_fdunlock(p);
 1014 
 1015                 if ( (fp->f_type == DTYPE_VNODE) && kauth_authorize_fileop_has_listeners() ) {
 1016                         /*
 1017                          * call out to allow 3rd party notification of close. 
 1018                          * Ignore result of kauth_authorize_fileop call.
 1019                          */
 1020                         if (vnode_getwithref((vnode_t)fp->f_data) == 0) {
 1021                                 u_int   fileop_flags = 0;
 1022                                 if ((fp->f_flags & FP_WRITTEN) != 0)
 1023                                         fileop_flags |= KAUTH_FILEOP_CLOSE_MODIFIED;
 1024                                 kauth_authorize_fileop(fp->f_fglob->fg_cred, KAUTH_FILEOP_CLOSE, 
 1025                                                        (uintptr_t)fp->f_data, (uintptr_t)fileop_flags);
 1026                                 vnode_put((vnode_t)fp->f_data);
 1027                         }
 1028                 }
 1029                 if (fp->f_flags & FP_AIOISSUED)
 1030                         /*
 1031                          * cancel all async IO requests that can be cancelled.
 1032                          */
 1033                         _aio_close( p, fd );
 1034 
 1035                 proc_fdlock(p);
 1036         }
 1037 
 1038         if (fd < fdp->fd_knlistsize)
 1039                 knote_fdclose(p, fd);
 1040 
 1041         if (fp->f_flags & FP_WAITEVENT) 
 1042                 (void)waitevent_close(p, fp);
 1043 
 1044         if ((fp->f_flags & FP_INCHRREAD) == 0)
 1045                 fileproc_drain(p, fp);
 1046         if (norelse == 0)
 1047                 _fdrelse(fdp, fd);
 1048         error = closef_locked(fp, fp->f_fglob, p);
 1049         if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE)
 1050                 wakeup(&fp->f_flags);
 1051         fp->f_flags &= ~(FP_WAITCLOSE | FP_CLOSING);
 1052 
 1053         if (!locked)
 1054                 proc_fdunlock(p);
 1055 
 1056         FREE_ZONE(fp, sizeof *fp, M_FILEPROC);  
 1057         return(error);
 1058 }
 1059 
 1060 /*
 1061  * Return status information about a file descriptor.
 1062  *
 1063  * XXX switch on node type is bogus; need a stat in struct fileops instead.
 1064  */
 1065 static int
 1066 fstat1(struct proc *p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size)
 1067 {
 1068         struct fileproc *fp;
 1069         struct stat sb;
 1070         struct user_stat user_sb;
 1071         int error, my_size;
 1072         int funnel_state;
 1073         short type;
 1074         caddr_t data;
 1075         kauth_filesec_t fsec;
 1076         ssize_t xsecurity_bufsize;
 1077         int entrycount;
 1078         struct vfs_context context;
 1079 
 1080 
 1081         AUDIT_ARG(fd, fd);
 1082 
 1083         if ((error = fp_lookup(p, fd, &fp, 0)) != 0)
 1084                 return(error);
 1085         type = fp->f_type;
 1086         data = fp->f_data;
 1087         fsec = KAUTH_FILESEC_NONE;
 1088 
 1089         switch (type) {
 1090 
 1091         case DTYPE_VNODE:
 1092                 context.vc_proc = current_proc();
 1093                 context.vc_ucred = kauth_cred_get();
 1094                 if ((error = vnode_getwithref((vnode_t)data)) == 0) {
 1095                         /*
 1096                          * If the caller has the file open, and is not requesting extended security,
 1097                          * we are going to let them get the basic stat information.
 1098                          */
 1099                         if (xsecurity == USER_ADDR_NULL) {
 1100                                 error = vn_stat_noauth((vnode_t)data, &sb, NULL, &context);
 1101                         } else {
 1102                                 error = vn_stat((vnode_t)data, &sb, &fsec, &context);
 1103                         }
 1104 
 1105                         AUDIT_ARG(vnpath, (struct vnode *)data, ARG_VNODE1);
 1106                         (void)vnode_put((vnode_t)data);
 1107                 }
 1108                 break;
 1109 
 1110         case DTYPE_SOCKET:
 1111                 error = soo_stat((struct socket *)data, &sb);
 1112                 break;
 1113 
 1114         case DTYPE_PIPE:
 1115                 error = pipe_stat((void *)data, &sb);
 1116                 break;
 1117 
 1118         case DTYPE_PSXSHM:
 1119                 error = pshm_stat((void *)data, &sb);
 1120                 break;
 1121 
 1122         case DTYPE_KQUEUE:
 1123                 funnel_state = thread_funnel_set(kernel_flock, TRUE);
 1124                 error = kqueue_stat(fp, &sb, p);
 1125                 thread_funnel_set(kernel_flock, funnel_state);
 1126                 break;
 1127 
 1128         default:
 1129                 error = EBADF;
 1130                 goto out;
 1131         }
 1132         /* Zap spare fields */
 1133         sb.st_lspare = 0;
 1134         sb.st_qspare[0] = 0LL;
 1135         sb.st_qspare[1] = 0LL;
 1136         if (error == 0) {
 1137                 caddr_t sbp;
 1138                 if (IS_64BIT_PROCESS(current_proc())) {
 1139                         munge_stat(&sb, &user_sb); 
 1140                         my_size = sizeof(user_sb);
 1141                         sbp = (caddr_t)&user_sb;
 1142                 }
 1143                 else {
 1144                         my_size = sizeof(sb);
 1145                         sbp = (caddr_t)&sb;
 1146                 }
 1147                 error = copyout(sbp, ub, my_size);
 1148         }
 1149 
 1150         /* caller wants extended security information? */
 1151         if (xsecurity != USER_ADDR_NULL) {
 1152 
 1153                 /* did we get any? */
 1154                  if (fsec == KAUTH_FILESEC_NONE) {
 1155                         if (susize(xsecurity_size, 0) != 0) {
 1156                                 error = EFAULT;
 1157                                 goto out;
 1158                         }
 1159                 } else {
 1160                         /* find the user buffer size */
 1161                         xsecurity_bufsize = fusize(xsecurity_size);
 1162 
 1163                         /* copy out the actual data size */
 1164                         if (susize(xsecurity_size, KAUTH_FILESEC_COPYSIZE(fsec)) != 0) {
 1165                                 error = EFAULT;
 1166                                 goto out;
 1167                         }
 1168 
 1169                         /* if the caller supplied enough room, copy out to it */
 1170                         if (xsecurity_bufsize >= KAUTH_FILESEC_COPYSIZE(fsec))
 1171                                 error = copyout(fsec, xsecurity, KAUTH_FILESEC_COPYSIZE(fsec));
 1172                 }
 1173         }
 1174 out:
 1175         fp_drop(p, fd, fp, 0);
 1176         if (fsec != NULL)
 1177                 kauth_filesec_free(fsec);
 1178         return (error);
 1179 }
 1180 
 1181 int
 1182 fstat_extended(struct proc *p, struct fstat_extended_args *uap, __unused register_t *retval)
 1183 {
 1184         return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size));
 1185 }
 1186  
 1187 int
 1188 fstat(struct proc *p, register struct fstat_args *uap, __unused register_t *retval)
 1189 {
 1190         return(fstat1(p, uap->fd, uap->ub, 0, 0));
 1191 }
 1192 
 1193 /*
 1194  * Return pathconf information about a file descriptor.
 1195  */
 1196 int
 1197 fpathconf(p, uap, retval)
 1198         struct proc *p;
 1199         register struct fpathconf_args *uap;
 1200         register_t *retval;
 1201 {
 1202         int fd = uap->fd;
 1203         struct fileproc *fp;
 1204         struct vnode *vp;
 1205         struct vfs_context context;
 1206         int error = 0;
 1207         short type;
 1208         caddr_t data;
 1209 
 1210 
 1211         AUDIT_ARG(fd, uap->fd);
 1212         if ( (error = fp_lookup(p, fd, &fp, 0)) )
 1213                 return(error);
 1214         type = fp->f_type;
 1215         data = fp->f_data;
 1216 
 1217         switch (type) {
 1218 
 1219         case DTYPE_SOCKET:
 1220                 if (uap->name != _PC_PIPE_BUF) {
 1221                         error = EINVAL;
 1222                         goto out;
 1223                 }
 1224                 *retval = PIPE_BUF;
 1225                 error = 0;
 1226                 goto out;
 1227 
 1228         case DTYPE_PIPE:
 1229                 *retval = PIPE_BUF;
 1230                 error = 0;
 1231                 goto out;
 1232 
 1233         case DTYPE_VNODE:
 1234                 vp = (struct vnode *)data;
 1235 
 1236                 if ( (error = vnode_getwithref(vp)) == 0) {
 1237                         AUDIT_ARG(vnpath, vp, ARG_VNODE1);
 1238 
 1239                         context.vc_proc = p;
 1240                         context.vc_ucred = kauth_cred_get();
 1241 
 1242                         error = vn_pathconf(vp, uap->name, retval, &context);
 1243 
 1244                         (void)vnode_put(vp);
 1245                 }
 1246                 goto out;
 1247 
 1248         case DTYPE_PSXSHM:
 1249         case DTYPE_KQUEUE:
 1250                 error = EINVAL;
 1251                 goto out;
 1252 
 1253         default:
 1254                 panic("fpathconf (unrecognized - %d)", type);
 1255         }
 1256         /*NOTREACHED*/
 1257 out:
 1258         fp_drop(p, fd, fp, 0);
 1259         return(error);
 1260 }
 1261 
 1262 /*
 1263  * Allocate a file descriptor for the process.
 1264  */
 1265 int fdexpand;
 1266 
 1267 int
 1268 fdalloc(p, want, result)
 1269         struct proc *p;
 1270         int want;
 1271         int *result;
 1272 {
 1273         register struct filedesc *fdp = p->p_fd;
 1274         register int i;
 1275         int lim, last, numfiles, oldnfiles;
 1276         struct fileproc **newofiles, **ofiles;
 1277         char *newofileflags, *ofileflags;
 1278 
 1279         /*
 1280          * Search for a free descriptor starting at the higher
 1281          * of want or fd_freefile.  If that fails, consider
 1282          * expanding the ofile array.
 1283          */
 1284         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
 1285         for (;;) {
 1286                 last = min(fdp->fd_nfiles, lim);
 1287                 if ((i = want) < fdp->fd_freefile)
 1288                         i = fdp->fd_freefile;
 1289                 ofiles = &fdp->fd_ofiles[i];
 1290                 ofileflags = &fdp->fd_ofileflags[i];
 1291                 for (; i < last; i++) {
 1292                         if (*ofiles == NULL && !(*ofileflags & UF_RESERVED)) {
 1293                                 *ofileflags = UF_RESERVED;
 1294                                 if (i > fdp->fd_lastfile)
 1295                                         fdp->fd_lastfile = i;
 1296                                 if (want <= fdp->fd_freefile)
 1297                                         fdp->fd_freefile = i;
 1298                                 *result = i;
 1299                                 return (0);
 1300                         }
 1301                         ofiles++; ofileflags++;
 1302                 }
 1303 
 1304                 /*
 1305                  * No space in current array.  Expand?
 1306                  */
 1307                 if (fdp->fd_nfiles >= lim)
 1308                         return (EMFILE);
 1309                 if (fdp->fd_nfiles < NDEXTENT)
 1310                         numfiles = NDEXTENT;
 1311                 else
 1312                         numfiles = 2 * fdp->fd_nfiles;
 1313                 /* Enforce lim */
 1314                 if (numfiles > lim)
 1315                         numfiles = lim;
 1316                 proc_fdunlock(p);
 1317                 MALLOC_ZONE(newofiles, struct fileproc **,
 1318                                 numfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
 1319                 proc_fdlock(p);
 1320                 if (newofiles == NULL) {
 1321                         return (ENOMEM);
 1322                 }
 1323                 if (fdp->fd_nfiles >= numfiles) {
 1324                         FREE_ZONE(newofiles, numfiles * OFILESIZE, M_OFILETABL);
 1325                         continue;
 1326                 }
 1327                 newofileflags = (char *) &newofiles[numfiles];
 1328                 /*
 1329                  * Copy the existing ofile and ofileflags arrays
 1330                  * and zero the new portion of each array.
 1331                  */
 1332                 oldnfiles = fdp->fd_nfiles;
 1333                 (void) memcpy(newofiles, fdp->fd_ofiles,
 1334                                 oldnfiles * sizeof *fdp->fd_ofiles);
 1335                 (void) memset(&newofiles[oldnfiles], 0,
 1336                                 (numfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
 1337 
 1338                 (void) memcpy(newofileflags, fdp->fd_ofileflags,
 1339                                 oldnfiles * sizeof *fdp->fd_ofileflags);
 1340                 (void) memset(&newofileflags[oldnfiles], 0,
 1341                                 (numfiles - oldnfiles) *
 1342                                                 sizeof *fdp->fd_ofileflags);
 1343                 ofiles = fdp->fd_ofiles;
 1344                 fdp->fd_ofiles = newofiles;
 1345                 fdp->fd_ofileflags = newofileflags;
 1346                 fdp->fd_nfiles = numfiles;
 1347                 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
 1348                 fdexpand++;
 1349         }
 1350 }
 1351 
 1352 /*
 1353  * Check to see whether n user file descriptors
 1354  * are available to the process p.
 1355  */
 1356 int
 1357 fdavail(p, n)
 1358         struct proc *p;
 1359         int n;
 1360 {
 1361         struct filedesc *fdp = p->p_fd;
 1362         struct fileproc **fpp;
 1363         char *flags;
 1364         int i, lim;
 1365 
 1366         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
 1367         if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
 1368                 return (1);
 1369         fpp = &fdp->fd_ofiles[fdp->fd_freefile];
 1370         flags = &fdp->fd_ofileflags[fdp->fd_freefile];
 1371         for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
 1372                 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
 1373                         return (1);
 1374         return (0);
 1375 }
 1376 
 1377 void
 1378 fdrelse(p, fd)
 1379         struct proc *p;
 1380         int fd;
 1381 {
 1382         _fdrelse(p->p_fd, fd);
 1383 }
 1384 
 1385 void
 1386 fddrop(p, fd)
 1387         struct proc *p;
 1388         int fd;
 1389 {
 1390         struct filedesc *fdp = p->p_fd;
 1391         struct fileproc *fp;
 1392 
 1393         if (fd < fdp->fd_freefile)
 1394                 fdp->fd_freefile = fd;
 1395 #if DIAGNOSTIC
 1396         if (fd > fdp->fd_lastfile)
 1397                 panic("fdrelse: fd_lastfile inconsistent");
 1398 #endif
 1399         fp = fdp->fd_ofiles[fd];
 1400         fdp->fd_ofiles[fd] = NULL;
 1401         fdp->fd_ofileflags[fd] = 0;
 1402 
 1403         while ((fd = fdp->fd_lastfile) > 0 &&
 1404                         fdp->fd_ofiles[fd] == NULL &&
 1405                         !(fdp->fd_ofileflags[fd] & UF_RESERVED))
 1406                 fdp->fd_lastfile--;
 1407         FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
 1408 }
 1409 
 1410 
 1411 int
 1412 fdgetf_noref(p, fd, resultfp)
 1413         struct proc *p;
 1414         int fd;
 1415         struct fileproc **resultfp;
 1416 {
 1417         struct filedesc *fdp = p->p_fd;
 1418         struct fileproc *fp;
 1419 
 1420         if (fd < 0 || fd >= fdp->fd_nfiles ||
 1421                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1422                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 1423                 return (EBADF);
 1424         }
 1425         if (resultfp)
 1426                 *resultfp = fp;
 1427         return (0);
 1428 }
 1429 
 1430 
 1431 /* should be called only when proc_fdlock is held */
 1432 void
 1433 fp_setflags(proc_t p, struct fileproc * fp, int flags)
 1434 {
 1435         proc_fdlock(p);
 1436         fp->f_flags |= flags;
 1437         proc_fdunlock(p);
 1438 }
 1439 
 1440 void
 1441 fp_clearflags(proc_t p, struct fileproc * fp, int flags)
 1442 {
 1443 
 1444         proc_fdlock(p);
 1445         if (fp)
 1446                 fp->f_flags &= ~flags;
 1447         proc_fdunlock(p);
 1448 }
 1449 
 1450 int
 1451 fp_getfvp(p, fd, resultfp, resultvp)
 1452         struct proc *p;
 1453         int fd;
 1454         struct fileproc **resultfp;
 1455         struct vnode  **resultvp;
 1456 {
 1457         struct filedesc *fdp = p->p_fd;
 1458         struct fileproc *fp;
 1459 
 1460         proc_fdlock(p);
 1461         if (fd < 0 || fd >= fdp->fd_nfiles ||
 1462                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1463                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 1464                 proc_fdunlock(p);
 1465                 return (EBADF);
 1466         }
 1467         if (fp->f_type != DTYPE_VNODE) {
 1468                 proc_fdunlock(p);
 1469                 return(ENOTSUP);
 1470         }
 1471         fp->f_iocount++;
 1472 
 1473         if (resultfp)
 1474                 *resultfp = fp;
 1475         if (resultvp)
 1476                 *resultvp = (struct vnode *)fp->f_data;
 1477         proc_fdunlock(p);
 1478 
 1479         return (0);
 1480 }
 1481 
 1482 
 1483 /*
 1484  * Returns:     EBADF                   The file descriptor is invalid
 1485  *              EOPNOTSUPP              The file descriptor is not a socket
 1486  *              0                       Success
 1487  *
 1488  * Notes:       EOPNOTSUPP should probably be ENOTSOCK; this function is only
 1489  *              ever called from accept1().
 1490  */
 1491 int
 1492 fp_getfsock(p, fd, resultfp, results)
 1493         struct proc *p;
 1494         int fd;
 1495         struct fileproc **resultfp;
 1496         struct socket  **results;
 1497 {
 1498         struct filedesc *fdp = p->p_fd;
 1499         struct fileproc *fp;
 1500 
 1501         proc_fdlock(p);
 1502         if (fd < 0 || fd >= fdp->fd_nfiles ||
 1503                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1504                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 1505                 proc_fdunlock(p);
 1506                 return (EBADF);
 1507         }
 1508         if (fp->f_type != DTYPE_SOCKET) {
 1509                 proc_fdunlock(p);
 1510                 return(EOPNOTSUPP);
 1511         }
 1512         fp->f_iocount++;
 1513 
 1514         if (resultfp)
 1515                 *resultfp = fp;
 1516         if (results)
 1517                 *results = (struct socket *)fp->f_data;
 1518         proc_fdunlock(p);
 1519 
 1520         return (0);
 1521 }
 1522 
 1523 
 1524 int
 1525 fp_getfkq(p, fd, resultfp, resultkq)
 1526         struct proc *p;
 1527         int fd;
 1528         struct fileproc **resultfp;
 1529         struct kqueue  **resultkq;
 1530 {
 1531         struct filedesc *fdp = p->p_fd;
 1532         struct fileproc *fp;
 1533 
 1534         proc_fdlock(p);
 1535         if ( fd < 0 || fd >= fdp->fd_nfiles ||
 1536                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1537                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 1538                 proc_fdunlock(p);
 1539                 return (EBADF);
 1540         }
 1541         if (fp->f_type != DTYPE_KQUEUE) {
 1542                 proc_fdunlock(p);
 1543                 return(EBADF);
 1544         }
 1545         fp->f_iocount++;
 1546 
 1547         if (resultfp)
 1548                 *resultfp = fp;
 1549         if (resultkq)
 1550                 *resultkq = (struct kqueue *)fp->f_data;
 1551         proc_fdunlock(p);
 1552 
 1553         return (0);
 1554 }
 1555 
 1556 int
 1557 fp_getfpshm(p, fd, resultfp, resultpshm)
 1558         struct proc *p;
 1559         int fd;
 1560         struct fileproc **resultfp;
 1561         struct pshmnode  **resultpshm;
 1562 {
 1563         struct filedesc *fdp = p->p_fd;
 1564         struct fileproc *fp;
 1565 
 1566         proc_fdlock(p);
 1567         if (fd < 0 || fd >= fdp->fd_nfiles ||
 1568                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1569                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 1570                 proc_fdunlock(p);
 1571                 return (EBADF);
 1572         }
 1573         if (fp->f_type != DTYPE_PSXSHM) {
 1574 
 1575                 proc_fdunlock(p);
 1576                 return(EBADF);
 1577         }
 1578         fp->f_iocount++;
 1579 
 1580         if (resultfp)
 1581                 *resultfp = fp;
 1582         if (resultpshm)
 1583                 *resultpshm = (struct pshmnode *)fp->f_data;
 1584         proc_fdunlock(p);
 1585 
 1586         return (0);
 1587 }
 1588 
 1589 
 1590 int
 1591 fp_getfpsem(p, fd, resultfp, resultpsem)
 1592         struct proc *p;
 1593         int fd;
 1594         struct fileproc **resultfp;
 1595         struct psemnode  **resultpsem;
 1596 {
 1597         struct filedesc *fdp = p->p_fd;
 1598         struct fileproc *fp;
 1599 
 1600         proc_fdlock(p);
 1601         if (fd < 0 || fd >= fdp->fd_nfiles ||
 1602                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1603                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 1604                 proc_fdunlock(p);
 1605                 return (EBADF);
 1606         }
 1607         if (fp->f_type != DTYPE_PSXSEM) {
 1608                 proc_fdunlock(p);
 1609                 return(EBADF);
 1610         }
 1611         fp->f_iocount++;
 1612 
 1613         if (resultfp)
 1614                 *resultfp = fp;
 1615         if (resultpsem)
 1616                 *resultpsem = (struct psemnode *)fp->f_data;
 1617         proc_fdunlock(p);
 1618 
 1619         return (0);
 1620 }
 1621 int
 1622 fp_lookup(p, fd, resultfp, locked)
 1623         struct proc *p;
 1624         int fd;
 1625         struct fileproc **resultfp;
 1626         int locked;
 1627 {
 1628         struct filedesc *fdp = p->p_fd;
 1629         struct fileproc *fp;
 1630 
 1631         if (!locked)
 1632                 proc_fdlock(p);
 1633         if (fd < 0 || fd >= fdp->fd_nfiles ||
 1634                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1635                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 1636                 if (!locked)
 1637                         proc_fdunlock(p);
 1638                 return (EBADF);
 1639         }
 1640         fp->f_iocount++;
 1641 
 1642         if (resultfp)
 1643                 *resultfp = fp;
 1644         if (!locked)
 1645                 proc_fdunlock(p);
 1646                 
 1647         return (0);
 1648 }
 1649 
 1650 int
 1651 fp_drop_written(proc_t p, int fd, struct fileproc *fp)
 1652 {
 1653         int error;
 1654 
 1655         proc_fdlock(p);
 1656 
 1657         fp->f_flags |= FP_WRITTEN;
 1658         
 1659         error = fp_drop(p, fd, fp, 1);
 1660 
 1661         proc_fdunlock(p);
 1662                 
 1663         return (error);
 1664 }
 1665 
 1666 
 1667 int
 1668 fp_drop_event(proc_t p, int fd, struct fileproc *fp)
 1669 {
 1670         int error;
 1671 
 1672         proc_fdlock(p);
 1673 
 1674         fp->f_flags |= FP_WAITEVENT;
 1675         
 1676         error = fp_drop(p, fd, fp, 1);
 1677 
 1678         proc_fdunlock(p);
 1679                 
 1680         return (error);
 1681 }
 1682 
 1683 int
 1684 fp_drop(p, fd, fp, locked)
 1685         struct proc *p;
 1686         int fd;
 1687         struct fileproc *fp;
 1688         int locked;
 1689 {
 1690         struct filedesc *fdp = p->p_fd;
 1691 
 1692         if (!locked)
 1693                 proc_fdlock(p);
 1694          if ((fp == FILEPROC_NULL) && (fd < 0 || fd >= fdp->fd_nfiles ||
 1695                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1696                         ((fdp->fd_ofileflags[fd] & UF_RESERVED) &&
 1697                          !(fdp->fd_ofileflags[fd] & UF_CLOSING)))) {
 1698                 if (!locked)
 1699                         proc_fdunlock(p);
 1700                 return (EBADF);
 1701         }
 1702         fp->f_iocount--;
 1703 
 1704         if (p->p_fpdrainwait && fp->f_iocount == 0) {
 1705                 p->p_fpdrainwait = 0;
 1706                 wakeup(&p->p_fpdrainwait);
 1707         }
 1708         if (!locked)
 1709                 proc_fdunlock(p);
 1710                 
 1711         return (0);
 1712 }
 1713 
 1714 int
 1715 file_vnode(int fd, struct vnode **vpp)
 1716 {
 1717         struct proc * p = current_proc();
 1718         struct fileproc *fp;
 1719         int error;
 1720         
 1721         proc_fdlock(p);
 1722         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
 1723                 proc_fdunlock(p);
 1724                 return(error);
 1725         }
 1726         if (fp->f_type != DTYPE_VNODE) {
 1727                 fp_drop(p, fd, fp,1);
 1728                 proc_fdunlock(p);
 1729                 return(EINVAL);
 1730         }
 1731         *vpp = (struct vnode *)fp->f_data;
 1732         proc_fdunlock(p);
 1733 
 1734         return(0);
 1735 }
 1736 
 1737 
 1738 int
 1739 file_socket(int fd, struct socket **sp)
 1740 {
 1741         struct proc * p = current_proc();
 1742         struct fileproc *fp;
 1743         int error;
 1744         
 1745         proc_fdlock(p);
 1746         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
 1747                 proc_fdunlock(p);
 1748                 return(error);
 1749         }
 1750         if (fp->f_type != DTYPE_SOCKET) {
 1751                 fp_drop(p, fd, fp,1);
 1752                 proc_fdunlock(p);
 1753                 return(ENOTSOCK);
 1754         }
 1755         *sp = (struct socket *)fp->f_data;
 1756         proc_fdunlock(p);
 1757 
 1758         return(0);
 1759 }
 1760 
 1761 int
 1762 file_flags(int fd, int * flags)
 1763 {
 1764 
 1765         struct proc * p = current_proc();
 1766         struct fileproc *fp;
 1767         int error;
 1768         
 1769         proc_fdlock(p);
 1770         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
 1771                 proc_fdunlock(p);
 1772                 return(error);
 1773         }
 1774         *flags = (int)fp->f_flag;
 1775         fp_drop(p, fd, fp,1);
 1776         proc_fdunlock(p);
 1777 
 1778         return(0);
 1779 }
 1780 
 1781 
 1782 int 
 1783 file_drop(int fd)
 1784 {
 1785         struct fileproc *fp;
 1786         struct proc *p = current_proc();
 1787 
 1788         proc_fdlock(p);
 1789         if (fd < 0 || fd >= p->p_fd->fd_nfiles ||
 1790                         (fp = p->p_fd->fd_ofiles[fd]) == NULL ||
 1791                         ((p->p_fd->fd_ofileflags[fd] & UF_RESERVED) &&
 1792                          !(p->p_fd->fd_ofileflags[fd] & UF_CLOSING))) {
 1793                 proc_fdunlock(p);
 1794                 return (EBADF);
 1795         }
 1796         fp->f_iocount --;
 1797 
 1798         if (p->p_fpdrainwait && fp->f_iocount == 0) {
 1799                 p->p_fpdrainwait = 0;
 1800                 wakeup(&p->p_fpdrainwait);
 1801         }
 1802         proc_fdunlock(p);
 1803         return(0);
 1804 
 1805 
 1806 }
 1807 
 1808 int
 1809 falloc(p, resultfp, resultfd )
 1810         struct proc *p;
 1811         struct fileproc **resultfp;
 1812         int *resultfd;
 1813 {
 1814         int error;
 1815 
 1816         proc_fdlock(p);
 1817         error = falloc_locked(p, resultfp, resultfd, 1);
 1818         proc_fdunlock(p);
 1819 
 1820         return(error);
 1821 }
 1822 /*
 1823  * Create a new open file structure and allocate
 1824  * a file decriptor for the process that refers to it.
 1825  */
 1826 int
 1827 falloc_locked(p, resultfp, resultfd, locked)
 1828         struct proc *p;
 1829         struct fileproc **resultfp;
 1830         int *resultfd;
 1831         int locked;
 1832 {
 1833         struct fileproc *fp, *fq;
 1834         struct fileglob *fg;
 1835         int error, nfd;
 1836 
 1837         if (!locked)
 1838                 proc_fdlock(p);
 1839         if ( (error = fdalloc(p, 0, &nfd)) ) {
 1840                 if (!locked)
 1841                         proc_fdunlock(p);
 1842                 return (error);
 1843         }
 1844         if (nfiles >= maxfiles) {
 1845                 if (!locked)
 1846                         proc_fdunlock(p);
 1847                 tablefull("file");
 1848                 return (ENFILE);
 1849         }
 1850         /*
 1851          * Allocate a new file descriptor.
 1852          * If the process has file descriptor zero open, add to the list
 1853          * of open files at that point, otherwise put it at the front of
 1854          * the list of open files.
 1855          */
 1856         proc_fdunlock(p);
 1857 
 1858         MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
 1859         MALLOC_ZONE(fg, struct fileglob *, sizeof(struct fileglob), M_FILEGLOB, M_WAITOK);
 1860         bzero(fp, sizeof(struct fileproc));
 1861         bzero(fg, sizeof(struct fileglob));
 1862         lck_mtx_init(&fg->fg_lock, file_lck_grp, file_lck_attr);
 1863 
 1864         fp->f_iocount = 1;
 1865         fg->fg_count = 1;
 1866         fp->f_fglob = fg;
 1867 
 1868         proc_fdlock(p);
 1869 
 1870         fp->f_cred = kauth_cred_proc_ref(p);
 1871 
 1872         lck_mtx_lock(file_flist_lock);
 1873 
 1874         nfiles++;
 1875 
 1876         if ( (fq = p->p_fd->fd_ofiles[0]) ) {
 1877                 LIST_INSERT_AFTER(fq->f_fglob, fg, f_list);
 1878         } else {
 1879                 LIST_INSERT_HEAD(&filehead, fg, f_list);
 1880         }
 1881         lck_mtx_unlock(file_flist_lock);
 1882 
 1883         p->p_fd->fd_ofiles[nfd] = fp;
 1884 
 1885         if (!locked)
 1886                 proc_fdunlock(p);
 1887 
 1888         if (resultfp)
 1889                 *resultfp = fp;
 1890         if (resultfd)
 1891                 *resultfd = nfd;
 1892 
 1893         return (0);
 1894 }
 1895 
 1896 /*
 1897  * Free a file structure.
 1898  */
 1899 void
 1900 fg_free(fg)
 1901         struct fileglob *fg;
 1902 {
 1903         kauth_cred_t cred;
 1904 
 1905         lck_mtx_lock(file_flist_lock);
 1906         LIST_REMOVE(fg, f_list);
 1907         nfiles--;
 1908         lck_mtx_unlock(file_flist_lock);
 1909 
 1910         cred = fg->fg_cred;
 1911         if (cred != NOCRED) {
 1912                 fg->fg_cred = NOCRED;
 1913                 kauth_cred_rele(cred);
 1914         }
 1915         lck_mtx_destroy(&fg->fg_lock, file_lck_grp);
 1916 
 1917         FREE_ZONE(fg, sizeof *fg, M_FILEGLOB);
 1918 }
 1919 
 1920 void
 1921 fdexec(p)
 1922         struct proc *p;
 1923 {
 1924         struct filedesc *fdp = p->p_fd;
 1925         int i = fdp->fd_lastfile;
 1926         struct fileproc **fpp = &fdp->fd_ofiles[i];
 1927         char *flags = &fdp->fd_ofileflags[i];
 1928         int funnel_state;
 1929 
 1930         funnel_state = thread_funnel_set(kernel_flock, FALSE);
 1931         proc_fdlock(p);
 1932 
 1933         while (i >= 0) {
 1934                 if ((*flags & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
 1935                         struct fileproc *fp = *fpp;
 1936 
 1937                         if (i < fdp->fd_knlistsize)
 1938                                 knote_fdclose(p, i);
 1939 
 1940                         *fpp = NULL; *flags = 0;
 1941                         if (i == fdp->fd_lastfile && i > 0)
 1942                                 fdp->fd_lastfile--;
 1943                         closef_locked(fp, fp->f_fglob, p);
 1944                         FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
 1945                 }
 1946 
 1947                 i--; fpp--; flags--;
 1948         }
 1949         proc_fdunlock(p);
 1950         thread_funnel_set(kernel_flock, funnel_state);
 1951 }
 1952 
 1953 /*
 1954  * Copy a filedesc structure.
 1955  */
 1956 struct filedesc *
 1957 fdcopy(p)
 1958         struct proc *p;
 1959 {
 1960         struct filedesc *newfdp, *fdp = p->p_fd;
 1961         int i;
 1962         struct fileproc *ofp, *fp;
 1963         vnode_t v_dir;
 1964 
 1965         MALLOC_ZONE(newfdp, struct filedesc *,
 1966                         sizeof *newfdp, M_FILEDESC, M_WAITOK);
 1967         if (newfdp == NULL)
 1968                 return(NULL);
 1969 
 1970         proc_fdlock(p);
 1971 
 1972         /*
 1973          * the FD_CHROOT flag will be inherited via this copy
 1974          */
 1975         (void) memcpy(newfdp, fdp, sizeof *newfdp);
 1976 
 1977         /*
 1978          * for both fd_cdir and fd_rdir make sure we get
 1979          * a valid reference... if we can't, than set
 1980          * set the pointer(s) to NULL in the child... this
 1981          * will keep us from using a non-referenced vp
 1982          * and allows us to do the vnode_rele only on
 1983          * a properly referenced vp
 1984          */
 1985         if ( (v_dir = newfdp->fd_cdir) ) {
 1986                 if (vnode_getwithref(v_dir) == 0) {
 1987                         if ( (vnode_ref(v_dir)) )
 1988                                 newfdp->fd_cdir = NULL;
 1989                         vnode_put(v_dir);
 1990                 } else
 1991                         newfdp->fd_cdir = NULL;
 1992         }
 1993         if (newfdp->fd_cdir == NULL && fdp->fd_cdir) {
 1994                 /*
 1995                  * we couldn't get a new reference on
 1996                  * the current working directory being
 1997                  * inherited... we might as well drop
 1998                  * our reference from the parent also
 1999                  * since the vnode has gone DEAD making
 2000                  * it useless... by dropping it we'll
 2001                  * be that much closer to recyling it
 2002                  */
 2003                 vnode_rele(fdp->fd_cdir);
 2004                 fdp->fd_cdir = NULL;
 2005         }
 2006 
 2007         if ( (v_dir = newfdp->fd_rdir) ) {
 2008                 if (vnode_getwithref(v_dir) == 0) {
 2009                         if ( (vnode_ref(v_dir)) )
 2010                                 newfdp->fd_rdir = NULL;
 2011                         vnode_put(v_dir);
 2012                 } else
 2013                         newfdp->fd_rdir = NULL;
 2014         }
 2015         if (newfdp->fd_rdir == NULL && fdp->fd_rdir) {
 2016                 /*
 2017                  * we couldn't get a new reference on
 2018                  * the root directory being
 2019                  * inherited... we might as well drop
 2020                  * our reference from the parent also
 2021                  * since the vnode has gone DEAD making
 2022                  * it useless... by dropping it we'll
 2023                  * be that much closer to recyling it
 2024                  */
 2025                 vnode_rele(fdp->fd_rdir);
 2026                 fdp->fd_rdir = NULL;
 2027         }
 2028         newfdp->fd_refcnt = 1;
 2029 
 2030         /*
 2031          * If the number of open files fits in the internal arrays
 2032          * of the open file structure, use them, otherwise allocate
 2033          * additional memory for the number of descriptors currently
 2034          * in use.
 2035          */
 2036         if (newfdp->fd_lastfile < NDFILE)
 2037                 i = NDFILE;
 2038         else {
 2039                 /*
 2040                  * Compute the smallest multiple of NDEXTENT needed
 2041                  * for the file descriptors currently in use,
 2042                  * allowing the table to shrink.
 2043                  */
 2044                 i = newfdp->fd_nfiles;
 2045                 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
 2046                         i /= 2;
 2047         }
 2048         proc_fdunlock(p);
 2049 
 2050         MALLOC_ZONE(newfdp->fd_ofiles, struct fileproc **,
 2051                                 i * OFILESIZE, M_OFILETABL, M_WAITOK);
 2052         if (newfdp->fd_ofiles == NULL) {
 2053                 if (newfdp->fd_cdir)
 2054                         vnode_rele(newfdp->fd_cdir);
 2055                 if (newfdp->fd_rdir)
 2056                         vnode_rele(newfdp->fd_rdir);
 2057 
 2058                 FREE_ZONE(newfdp, sizeof *newfdp, M_FILEDESC);
 2059                 return(NULL);
 2060         }
 2061         proc_fdlock(p);
 2062 
 2063         newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
 2064         newfdp->fd_nfiles = i;
 2065 
 2066         if (fdp->fd_nfiles > 0) {
 2067                 struct fileproc **fpp;
 2068                 char *flags;
 2069 
 2070                 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
 2071                                         i * sizeof *fdp->fd_ofiles);
 2072                 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
 2073                                         i * sizeof *fdp->fd_ofileflags);
 2074 
 2075                 /*
 2076                  * kq descriptors cannot be copied.
 2077                  */
 2078                 if (newfdp->fd_knlistsize != -1) {
 2079                         fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
 2080                         for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
 2081                                 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
 2082                                         *fpp = NULL;
 2083                                         if (i < newfdp->fd_freefile)
 2084                                                 newfdp->fd_freefile = i;
 2085                                 }
 2086                                 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
 2087                                         newfdp->fd_lastfile--;
 2088                         }
 2089                         newfdp->fd_knlist = NULL;
 2090                         newfdp->fd_knlistsize = -1;
 2091                         newfdp->fd_knhash = NULL;
 2092                         newfdp->fd_knhashmask = 0;
 2093                 }
 2094                 fpp = newfdp->fd_ofiles;
 2095                 flags = newfdp->fd_ofileflags;
 2096 
 2097                 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++, flags++)
 2098                         if ((ofp = *fpp) != NULL && !(*flags & UF_RESERVED)) {
 2099                                 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
 2100                                 bzero(fp, sizeof(struct fileproc));
 2101                                 fp->f_flags = ofp->f_flags;
 2102                                 //fp->f_iocount = ofp->f_iocount;
 2103                                 fp->f_iocount = 0;
 2104                                 fp->f_fglob = ofp->f_fglob;
 2105                                 (void)fg_ref(fp);
 2106                                 *fpp = fp;
 2107                         } else {
 2108                                 *fpp = NULL;
 2109                                 *flags = 0;
 2110                         }
 2111         } else
 2112                 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
 2113 
 2114         proc_fdunlock(p);
 2115         return (newfdp);
 2116 }
 2117 
 2118 /*
 2119  * Release a filedesc structure.
 2120  */
 2121 void
 2122 fdfree(p)
 2123         struct proc *p;
 2124 {
 2125         struct filedesc *fdp;
 2126         struct fileproc *fp;
 2127         int i;
 2128 
 2129         proc_fdlock(p);
 2130 
 2131         /* Certain daemons might not have file descriptors */
 2132         fdp = p->p_fd;
 2133 
 2134         if ((fdp == NULL) || (--fdp->fd_refcnt > 0)) {
 2135                 proc_fdunlock(p);
 2136                 return;
 2137         }
 2138         if (fdp->fd_refcnt == 0xffff)
 2139                 panic("fdfree: bad fd_refcnt");
 2140 
 2141         /* Last reference: the structure can't change out from under us */
 2142 
 2143         if (fdp->fd_nfiles > 0 && fdp->fd_ofiles) {
 2144                 for (i = fdp->fd_lastfile; i >= 0; i--) {
 2145                         if ((fp = fdp->fd_ofiles[i]) != NULL) {
 2146                           
 2147                           if (fdp->fd_ofileflags[i] & UF_RESERVED)
 2148                             panic("fdfree: found fp with UF_RESERVED\n");
 2149 
 2150                                 /* closef drops the iocount ... */
 2151                                 if ((fp->f_flags & FP_INCHRREAD) != 0) 
 2152                                         fp->f_iocount++;
 2153                             fdp->fd_ofiles[i] = NULL;
 2154                                 fdp->fd_ofileflags[i] |= UF_RESERVED;
 2155 
 2156                                 if (i < fdp->fd_knlistsize)
 2157                                         knote_fdclose(p, i);
 2158                                 if (fp->f_flags & FP_WAITEVENT) 
 2159                                         (void)waitevent_close(p, fp);
 2160                                 (void) closef_locked(fp, fp->f_fglob, p);
 2161                                 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
 2162                         }
 2163                 }
 2164                 FREE_ZONE(fdp->fd_ofiles, fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
 2165                 fdp->fd_ofiles = NULL;
 2166                 fdp->fd_nfiles = 0;
 2167         }        
 2168 
 2169         proc_fdunlock(p);
 2170         
 2171         if (fdp->fd_cdir)
 2172                 vnode_rele(fdp->fd_cdir);
 2173         if (fdp->fd_rdir)
 2174                 vnode_rele(fdp->fd_rdir);
 2175 
 2176         proc_fdlock(p);
 2177         p->p_fd = NULL;
 2178         proc_fdunlock(p);
 2179 
 2180         if (fdp->fd_knlist)
 2181                 FREE(fdp->fd_knlist, M_KQUEUE);
 2182         if (fdp->fd_knhash)
 2183                 FREE(fdp->fd_knhash, M_KQUEUE);
 2184 
 2185         FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
 2186 }
 2187 
 2188 static int
 2189 closef_finish(fp, fg, p)
 2190         struct fileproc *fp;
 2191         struct fileglob *fg;
 2192         struct proc *p;
 2193 {
 2194         struct vnode *vp;
 2195         struct flock lf;
 2196         int error;
 2197         struct vfs_context context;
 2198 
 2199         if ((fg->fg_flag & FHASLOCK) && fg->fg_type == DTYPE_VNODE) {
 2200                 lf.l_whence = SEEK_SET;
 2201                 lf.l_start = 0;
 2202                 lf.l_len = 0;
 2203                 lf.l_type = F_UNLCK;
 2204                 vp = (struct vnode *)fg->fg_data;
 2205                 context.vc_proc = p;
 2206                 context.vc_ucred = fg->fg_cred;
 2207 
 2208                 (void) VNOP_ADVLOCK(vp, (caddr_t)fg, F_UNLCK, &lf, F_FLOCK, &context);
 2209         }
 2210         if (fg->fg_ops)
 2211                 error = fo_close(fg, p);
 2212         else
 2213                 error = 0;
 2214 
 2215         if (((fp != (struct fileproc *)0) && ((fp->f_flags & FP_INCHRREAD) != 0))) {
 2216                 proc_fdlock(p);
 2217                 if ( ((fp->f_flags & FP_INCHRREAD) != 0) ) {
 2218                         fileproc_drain(p, fp);
 2219                 }
 2220                 proc_fdunlock(p);
 2221         }
 2222         fg_free(fg);
 2223 
 2224         return (error);
 2225 }
 2226 
 2227 int
 2228 closef(fg, p)
 2229         struct fileglob *fg;
 2230         struct proc *p;
 2231 {
 2232         int error;
 2233 
 2234         proc_fdlock(p);
 2235         error = closef_locked((struct fileproc *)0, fg, p);
 2236         proc_fdunlock(p);
 2237 
 2238         return(error);
 2239 }
 2240 /*
 2241  * Internal form of close.
 2242  * Decrement reference count on file structure.
 2243  * Note: p may be NULL when closing a file
 2244  * that was being passed in a message.
 2245  */
 2246 int
 2247 closef_locked(fp, fg, p)
 2248         struct fileproc *fp;
 2249         struct fileglob *fg;
 2250         struct proc *p;
 2251 {
 2252         struct vnode *vp;
 2253         struct flock lf;
 2254         struct vfs_context context;
 2255         int error;
 2256 
 2257         if (fg == NULL) {
 2258                 return (0);
 2259         }
 2260         /*
 2261          * POSIX record locking dictates that any close releases ALL
 2262          * locks owned by this process.  This is handled by setting
 2263          * a flag in the unlock to free ONLY locks obeying POSIX
 2264          * semantics, and not to free BSD-style file locks.
 2265          * If the descriptor was in a message, POSIX-style locks
 2266          * aren't passed with the descriptor.
 2267          */
 2268         if (p && (p->p_flag & P_ADVLOCK) && fg->fg_type == DTYPE_VNODE) {
 2269                 proc_fdunlock(p);
 2270 
 2271                 lf.l_whence = SEEK_SET;
 2272                 lf.l_start = 0;
 2273                 lf.l_len = 0;
 2274                 lf.l_type = F_UNLCK;
 2275                 vp = (struct vnode *)fg->fg_data;
 2276 
 2277                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 2278                         context.vc_proc = p;
 2279                         context.vc_ucred = fg->fg_cred;
 2280                         (void) VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX, &context);
 2281 
 2282                         (void)vnode_put(vp);
 2283                 }
 2284                 proc_fdlock(p);
 2285         }
 2286         lck_mtx_lock(&fg->fg_lock);
 2287         fg->fg_count--;
 2288 
 2289         if (fg->fg_count > 0) {
 2290                 lck_mtx_unlock(&fg->fg_lock);
 2291                 return (0);
 2292         }
 2293         if (fg->fg_count != 0)
 2294                 panic("fg: being freed with bad fg_count (%d)", fg, fg->fg_count);
 2295 
 2296         if (fp && (fp->f_flags & FP_WRITTEN))
 2297                 fg->fg_flag |= FWASWRITTEN;
 2298 
 2299         fg->fg_lflags |= FG_TERM;
 2300         lck_mtx_unlock(&fg->fg_lock);
 2301 
 2302         proc_fdunlock(p);
 2303         error = closef_finish(fp, fg, p);
 2304         proc_fdlock(p);
 2305 
 2306         return(error);
 2307 }
 2308 
 2309 
 2310 extern int selwait;
 2311 void
 2312 fileproc_drain(struct proc *p, struct fileproc * fp)
 2313 {
 2314         fp->f_iocount-- ; /* (the one the close holds) */
 2315 
 2316         while (fp->f_iocount) {
 2317                 if (((fp->f_flags & FP_INSELECT)== FP_INSELECT)) {
 2318                         wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, &selwait, THREAD_INTERRUPTED);
 2319                 } else  {
 2320                         if (fp->f_fglob->fg_ops->fo_drain) {
 2321                                 (*fp->f_fglob->fg_ops->fo_drain)(fp, p);
 2322                         }
 2323                 }
 2324                 p->p_fpdrainwait = 1;
 2325 
 2326                 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO, "fpdrain",0);
 2327 
 2328                 //panic("successful wait after drain\n");
 2329         }
 2330 }
 2331 
 2332 int
 2333 fp_free(struct proc * p, int fd, struct fileproc * fp)
 2334 {
 2335         proc_fdlock(p);
 2336         fdrelse(p, fd);
 2337         proc_fdunlock(p);
 2338 
 2339         fg_free(fp->f_fglob);
 2340         FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
 2341 }
 2342 
 2343 
 2344 /*
 2345  * Apply an advisory lock on a file descriptor.
 2346  *
 2347  * Just attempt to get a record lock of the requested type on
 2348  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
 2349  */
 2350 int
 2351 flock(struct proc *p, register struct flock_args *uap, __unused register_t *retval)
 2352 {
 2353         int fd = uap->fd;
 2354         int how = uap->how;
 2355         struct fileproc *fp;
 2356         struct vnode *vp;
 2357         struct flock lf;
 2358         struct vfs_context context;
 2359         int error=0;
 2360 
 2361         AUDIT_ARG(fd, uap->fd);
 2362         if ( (error = fp_getfvp(p, fd, &fp, &vp)) ) {
 2363                 return(error);
 2364         }
 2365         if ( (error = vnode_getwithref(vp)) ) {
 2366                 goto out1;
 2367         }
 2368         AUDIT_ARG(vnpath, vp, ARG_VNODE1);
 2369 
 2370         context.vc_proc = p;
 2371         context.vc_ucred = fp->f_cred;
 2372 
 2373         lf.l_whence = SEEK_SET;
 2374         lf.l_start = 0;
 2375         lf.l_len = 0;
 2376         if (how & LOCK_UN) {
 2377                 lf.l_type = F_UNLCK;
 2378                 fp->f_flag &= ~FHASLOCK;
 2379                 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_UNLCK, &lf, F_FLOCK, &context);
 2380                 goto out;
 2381         }
 2382         if (how & LOCK_EX)
 2383                 lf.l_type = F_WRLCK;
 2384         else if (how & LOCK_SH)
 2385                 lf.l_type = F_RDLCK;
 2386         else {
 2387                 error = EBADF;
 2388                 goto out;
 2389         }
 2390         fp->f_flag |= FHASLOCK;
 2391         if (how & LOCK_NB) {
 2392                 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK, &context);
 2393                 goto out;       
 2394         }
 2395         error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK|F_WAIT, &context);
 2396 out:
 2397         (void)vnode_put(vp);
 2398 out1:
 2399         fp_drop(p, fd, fp, 0);
 2400         return(error);
 2401 
 2402 }
 2403 
 2404 /*
 2405  * File Descriptor pseudo-device driver (/dev/fd/).
 2406  *
 2407  * Opening minor device N dup()s the file (if any) connected to file
 2408  * descriptor N belonging to the calling process.  Note that this driver
 2409  * consists of only the ``open()'' routine, because all subsequent
 2410  * references to this file will be direct to the other driver.
 2411  */
 2412 int
 2413 fdopen(dev_t dev, __unused int mode, __unused int type, struct proc *p)
 2414 {
 2415 
 2416         /*
 2417          * XXX Kludge: set curproc->p_dupfd to contain the value of the
 2418          * the file descriptor being sought for duplication. The error 
 2419          * return ensures that the vnode for this device will be released
 2420          * by vn_open. Open will detect this special error and take the
 2421          * actions in dupfdopen below. Other callers of vn_open or vnop_open
 2422          * will simply report the error.
 2423          */
 2424         p->p_dupfd = minor(dev);
 2425         return (ENODEV);
 2426 }
 2427 
 2428 /*
 2429  * Duplicate the specified descriptor to a free descriptor.
 2430  */
 2431 int
 2432 dupfdopen(fdp, indx, dfd, mode, error)
 2433         register struct filedesc *fdp;
 2434         register int indx, dfd;
 2435         int mode;
 2436         int error;
 2437 {
 2438         struct fileproc *wfp;
 2439         struct fileproc *fp;
 2440         struct proc * p = current_proc();
 2441 
 2442         /*
 2443          * If the to-be-dup'd fd number is greater than the allowed number
 2444          * of file descriptors, or the fd to be dup'd has already been
 2445          * closed, reject.  Note, check for new == old is necessary as
 2446          * falloc could allocate an already closed to-be-dup'd descriptor
 2447          * as the new descriptor.
 2448          */
 2449         proc_fdlock(p);
 2450 
 2451         fp = fdp->fd_ofiles[indx];
 2452         if (dfd < 0 || dfd >= fdp->fd_nfiles ||
 2453                         (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
 2454                         (fdp->fd_ofileflags[dfd] & UF_RESERVED)) {
 2455 
 2456                 proc_fdunlock(p);
 2457                 return (EBADF);
 2458         }
 2459         /*
 2460          * There are two cases of interest here.
 2461          *
 2462          * For ENODEV simply dup (dfd) to file descriptor
 2463          * (indx) and return.
 2464          *
 2465          * For ENXIO steal away the file structure from (dfd) and
 2466          * store it in (indx).  (dfd) is effectively closed by
 2467          * this operation.
 2468          *
 2469          * Any other error code is just returned.
 2470          */
 2471         switch (error) {
 2472         case ENODEV:
 2473                 /*
 2474                  * Check that the mode the file is being opened for is a
 2475                  * subset of the mode of the existing descriptor.
 2476                  */
 2477                 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
 2478                         proc_fdunlock(p);
 2479                         return (EACCES);
 2480                 }
 2481                 if (indx > fdp->fd_lastfile)
 2482                         fdp->fd_lastfile = indx;
 2483                 (void)fg_ref(wfp);
 2484 
 2485                 if (fp->f_fglob)
 2486                         fg_free(fp->f_fglob);
 2487                 fp->f_fglob = wfp->f_fglob;
 2488 
 2489                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 2490 
 2491                 proc_fdunlock(p);
 2492                 return (0);
 2493 
 2494         case ENXIO:
 2495                 /*
 2496                  * Steal away the file pointer from dfd, and stuff it into indx.
 2497                  */
 2498                 if (indx > fdp->fd_lastfile)
 2499                         fdp->fd_lastfile = indx;
 2500 
 2501                 if (fp->f_fglob)
 2502                         fg_free(fp->f_fglob);
 2503                 fp->f_fglob = wfp->f_fglob;
 2504 
 2505                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 2506                 _fdrelse(fdp, dfd);
 2507 
 2508                 proc_fdunlock(p);
 2509 
 2510                 FREE_ZONE(wfp, sizeof *fp, M_FILEPROC); 
 2511 
 2512                 return (0);
 2513 
 2514         default:
 2515                 proc_fdunlock(p);
 2516                 return (error);
 2517         }
 2518         /* NOTREACHED */
 2519 }
 2520 
 2521 void
 2522 fg_ref(struct fileproc * fp)
 2523 {
 2524         struct fileglob *fg;
 2525 
 2526         fg = fp->f_fglob;
 2527 
 2528         lck_mtx_lock(&fg->fg_lock);
 2529         fg->fg_count++;
 2530         lck_mtx_unlock(&fg->fg_lock);
 2531 }
 2532 
 2533 void
 2534 fg_drop(struct fileproc * fp)
 2535 {
 2536         struct fileglob *fg;
 2537 
 2538         fg = fp->f_fglob;
 2539         lck_mtx_lock(&fg->fg_lock);
 2540         fg->fg_count--;
 2541         lck_mtx_unlock(&fg->fg_lock);
 2542 }
 2543 
 2544 
 2545 void
 2546 fg_insertuipc(struct fileglob * fg)
 2547 {
 2548 int insertque = 0;
 2549 
 2550         lck_mtx_lock(&fg->fg_lock);
 2551 
 2552         while (fg->fg_lflags & FG_RMMSGQ) {
 2553                 fg->fg_lflags |= FG_WRMMSGQ;
 2554                 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", 0);
 2555         }
 2556 
 2557         fg->fg_count++;
 2558         fg->fg_msgcount++;
 2559         if (fg->fg_msgcount == 1) {
 2560                 fg->fg_lflags |= FG_INSMSGQ;
 2561                 insertque=1;
 2562         }
 2563         lck_mtx_unlock(&fg->fg_lock);
 2564 
 2565         if (insertque) {
 2566                 lck_mtx_lock(uipc_lock);
 2567                 LIST_INSERT_HEAD(&fmsghead, fg, f_msglist);
 2568                 lck_mtx_unlock(uipc_lock);
 2569                 lck_mtx_lock(&fg->fg_lock);
 2570                 fg->fg_lflags &= ~FG_INSMSGQ;
 2571                 if (fg->fg_lflags & FG_WINSMSGQ) {
 2572                         fg->fg_lflags &= ~FG_WINSMSGQ;
 2573                         wakeup(&fg->fg_lflags);
 2574                 }
 2575                 lck_mtx_unlock(&fg->fg_lock);
 2576         }
 2577 
 2578 }
 2579 
 2580 void
 2581 fg_removeuipc(struct fileglob * fg)
 2582 {
 2583 int removeque = 0;
 2584 
 2585         lck_mtx_lock(&fg->fg_lock);
 2586         while (fg->fg_lflags & FG_INSMSGQ) {
 2587                 fg->fg_lflags |= FG_WINSMSGQ;
 2588                 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", 0);
 2589         }
 2590         fg->fg_msgcount--;
 2591         if (fg->fg_msgcount == 0) {
 2592                 fg->fg_lflags |= FG_RMMSGQ;
 2593                 removeque=1;
 2594         }
 2595         lck_mtx_unlock(&fg->fg_lock);
 2596 
 2597         if (removeque) {
 2598                 lck_mtx_lock(uipc_lock);
 2599                 LIST_REMOVE(fg, f_msglist);
 2600                 lck_mtx_unlock(uipc_lock);
 2601                 lck_mtx_lock(&fg->fg_lock);
 2602                 fg->fg_lflags &= ~FG_RMMSGQ;
 2603                 if (fg->fg_lflags & FG_WRMMSGQ) {
 2604                         fg->fg_lflags &= ~FG_WRMMSGQ;
 2605                         wakeup(&fg->fg_lflags);
 2606                 }
 2607                 lck_mtx_unlock(&fg->fg_lock);
 2608         }
 2609 }
 2610 
 2611 
 2612 int
 2613 fo_read(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
 2614 {
 2615         return ((*fp->f_ops->fo_read)(fp, uio, cred, flags, p));
 2616 }
 2617 
 2618 int
 2619 fo_write(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
 2620 {
 2621         return((*fp->f_ops->fo_write)(fp, uio, cred, flags, p));
 2622 }
 2623 
 2624 int 
 2625 fo_ioctl(struct fileproc *fp, u_long com, caddr_t data, struct proc *p)
 2626 {
 2627 int error;
 2628 
 2629         proc_fdunlock(p);
 2630         error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
 2631         proc_fdlock(p);
 2632         return(error);
 2633 }       
 2634 
 2635 int
 2636 fo_select(struct fileproc *fp, int which, void *wql, struct proc *p)
 2637 {       
 2638         return((*fp->f_ops->fo_select)(fp, which, wql, p));
 2639 }
 2640 
 2641 int
 2642 fo_close(struct fileglob *fg, struct proc *p)
 2643 {       
 2644         return((*fg->fg_ops->fo_close)(fg, p));
 2645 }
 2646 
 2647 int
 2648 fo_kqfilter(struct fileproc *fp, struct knote *kn, struct proc *p)
 2649 {
 2650         return ((*fp->f_ops->fo_kqfilter)(fp, kn, p));
 2651 }
 2652 

Cache object: 3b485ef2fde15daccb9e7538190600f7


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