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

Cache object: c126785c6a805d0d941178738b328b68


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