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-2003 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
   26 /*
   27  * Copyright (c) 1982, 1986, 1989, 1991, 1993
   28  *      The Regents of the University of California.  All rights reserved.
   29  * (c) UNIX System Laboratories, Inc.
   30  * All or some portions of this file are derived from material licensed
   31  * to the University of California by American Telephone and Telegraph
   32  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   33  * the permission of UNIX System Laboratories, Inc.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. All advertising materials mentioning features or use of this software
   44  *    must display the following acknowledgement:
   45  *      This product includes software developed by the University of
   46  *      California, Berkeley and its contributors.
   47  * 4. Neither the name of the University nor the names of its contributors
   48  *    may be used to endorse or promote products derived from this software
   49  *    without specific prior written permission.
   50  *
   51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   61  * SUCH DAMAGE.
   62  *
   63  *      @(#)kern_descrip.c      8.8 (Berkeley) 2/14/95
   64  */
   65 
   66 #include <sys/param.h>
   67 #include <sys/systm.h>
   68 #include <sys/filedesc.h>
   69 #include <sys/kernel.h>
   70 #include <sys/vnode.h>
   71 #include <sys/proc.h>
   72 #include <sys/file.h>
   73 #include <sys/socket.h>
   74 #include <sys/socketvar.h>
   75 #include <sys/stat.h>
   76 #include <sys/ioctl.h>
   77 #include <sys/fcntl.h>
   78 #include <sys/malloc.h>
   79 #include <sys/syslog.h>
   80 #include <sys/unistd.h>
   81 #include <sys/resourcevar.h>
   82 #include <sys/aio_kern.h>
   83 #include <sys/kern_audit.h>
   84 
   85 #include <sys/mount.h>
   86 
   87 /*
   88  * Descriptor management.
   89  */
   90 struct filelist filehead;       /* head of list of open files */
   91 int nfiles;                     /* actual number of open files */
   92 
   93 static int frele_internal(struct file *);
   94 
   95 /*
   96  * System calls on descriptors.
   97  */
   98 /* ARGSUSED */
   99 int
  100 getdtablesize(p, uap, retval)
  101         struct proc *p;
  102         void *uap;
  103         register_t *retval;
  104 {
  105         *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
  106         return (0);
  107 }
  108 
  109 /* ARGSUSED */
  110 int
  111 ogetdtablesize(p, uap, retval)
  112         struct proc *p;
  113         void *uap;
  114         register_t *retval;
  115 {
  116         *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, NOFILE);
  117         return (0);
  118 }
  119 
  120 static __inline__
  121 void _fdrelse(fdp, fd)
  122         register struct filedesc *fdp;
  123         register int fd;
  124 {
  125         if (fd < fdp->fd_freefile)
  126                 fdp->fd_freefile = fd;
  127 #if DIAGNOSTIC
  128         if (fd > fdp->fd_lastfile)
  129                 panic("fdrelse: fd_lastfile inconsistent");
  130 #endif
  131         fdp->fd_ofiles[fd] = NULL;
  132         fdp->fd_ofileflags[fd] = 0;
  133         while ((fd = fdp->fd_lastfile) > 0 &&
  134                         fdp->fd_ofiles[fd] == NULL &&
  135                         !(fdp->fd_ofileflags[fd] & UF_RESERVED))
  136                 fdp->fd_lastfile--;
  137 }
  138 
  139 /*
  140  * Duplicate a file descriptor.
  141  */
  142 struct dup_args {
  143         u_int   fd;
  144 };
  145 /* ARGSUSED */
  146 int
  147 dup(p, uap, retval)
  148         struct proc *p;
  149         struct dup_args *uap;
  150         register_t *retval;
  151 {
  152         register struct filedesc *fdp = p->p_fd;
  153         register int old = uap->fd;
  154         int new, error;
  155 
  156         if ((u_int)old >= fdp->fd_nfiles ||
  157                         fdp->fd_ofiles[old] == NULL ||
  158                         (fdp->fd_ofileflags[old] & UF_RESERVED))
  159                 return (EBADF);
  160         if (error = fdalloc(p, 0, &new))
  161                 return (error);
  162         return (finishdup(fdp, old, new, retval));
  163 }
  164 
  165 /*
  166  * Duplicate a file descriptor to a particular value.
  167  */
  168 struct dup2_args {
  169         u_int   from;
  170         u_int   to;
  171 };
  172 /* ARGSUSED */
  173 int
  174 dup2(p, uap, retval)
  175         struct proc *p;
  176         struct dup2_args *uap;
  177         register_t *retval;
  178 {
  179         register struct filedesc *fdp = p->p_fd;
  180         register int old = uap->from, new = uap->to;
  181         int i, error;
  182 
  183         if ((u_int)old >= fdp->fd_nfiles ||
  184                 fdp->fd_ofiles[old] == NULL ||
  185                 (fdp->fd_ofileflags[old] & UF_RESERVED) ||
  186             (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  187             (u_int)new >= maxfiles)
  188                 return (EBADF);
  189         if (old == new) {
  190                 *retval = new;
  191                 return (0);
  192         }
  193         if ((u_int)new >= fdp->fd_nfiles) {
  194                 if (error = fdalloc(p, new, &i))
  195                         return (error);
  196                 if (new != i) {
  197                         _fdrelse(fdp, i);
  198                         goto closeit;
  199                 }
  200         } else {
  201                 struct file **fpp;
  202                 char flags;
  203 closeit:
  204                 if ((flags = fdp->fd_ofileflags[new]) & UF_RESERVED)
  205                         return (EBADF);
  206                 fdp->fd_ofileflags[new] = (flags & ~UF_MAPPED) | UF_RESERVED;
  207                 /*
  208                  * dup2() must succeed even if the close has an error.
  209                  */
  210                 if (*(fpp = &fdp->fd_ofiles[new])) {
  211                         struct file *fp = *fpp;
  212 
  213                         *fpp = NULL;
  214                         (void) closef(fp, p);
  215                 }
  216         }
  217         return (finishdup(fdp, old, new, retval));
  218 }
  219 
  220 /*
  221  * The file control system call.
  222  */
  223 struct fcntl_args {
  224         int     fd;
  225         int     cmd;
  226         int     arg;
  227 };
  228 /* ARGSUSED */
  229 int
  230 fcntl(p, uap, retval)
  231         struct proc *p;
  232         register struct fcntl_args *uap;
  233         register_t *retval;
  234 {
  235         int fd = uap->fd;
  236         register struct filedesc *fdp = p->p_fd;
  237         register struct file *fp;
  238         register char *pop;
  239         struct vnode *vp, *devvp;
  240         int i, tmp, error, error2, flg = F_POSIX;
  241         struct flock fl;
  242         fstore_t alloc_struct;    /* structure for allocate command */
  243         u_int32_t alloc_flags = 0;
  244         off_t offset;             /* used for F_SETSIZE */
  245         int newmin;
  246         struct radvisory ra_struct;
  247         fbootstraptransfer_t fbt_struct; /* for F_READBOOTSTRAP and F_WRITEBOOTSTRAP */
  248         struct log2phys l2p_struct;    /* structure for allocate command */
  249         daddr_t lbn, bn;
  250         int devBlockSize = 0;
  251 
  252         AUDIT_ARG(fd, uap->fd);
  253         AUDIT_ARG(cmd, uap->cmd);
  254         if ((u_int)fd >= fdp->fd_nfiles ||
  255                         (fp = fdp->fd_ofiles[fd]) == NULL ||
  256                         (fdp->fd_ofileflags[fd] & UF_RESERVED))
  257                 return (EBADF);
  258         pop = &fdp->fd_ofileflags[fd];
  259 
  260         switch (uap->cmd) {
  261 
  262         case F_DUPFD:
  263                 newmin = (long)uap->arg;
  264                 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  265                     (u_int)newmin >= maxfiles)
  266                         return (EINVAL);
  267                 if (error = fdalloc(p, newmin, &i))
  268                         return (error);
  269                 return (finishdup(fdp, fd, i, retval));
  270 
  271         case F_GETFD:
  272                 *retval = (*pop & UF_EXCLOSE)? 1 : 0;
  273                 return (0);
  274 
  275         case F_SETFD:
  276                 *pop = (*pop &~ UF_EXCLOSE) |
  277                         ((long)(uap->arg) & 1)? UF_EXCLOSE : 0;
  278                 return (0);
  279 
  280         case F_GETFL:
  281                 *retval = OFLAGS(fp->f_flag);
  282                 return (0);
  283 
  284         case F_SETFL:
  285                 fp->f_flag &= ~FCNTLFLAGS;
  286                 fp->f_flag |= FFLAGS((long)uap->arg) & FCNTLFLAGS;
  287                 tmp = fp->f_flag & FNONBLOCK;
  288                 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
  289                 if (error)
  290                         return (error);
  291                 tmp = fp->f_flag & FASYNC;
  292                 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
  293                 if (!error)
  294                         return (0);
  295                 fp->f_flag &= ~FNONBLOCK;
  296                 tmp = 0;
  297                 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
  298                 return (error);
  299 
  300         case F_GETOWN:
  301                 if (fp->f_type == DTYPE_SOCKET) {
  302                         *retval = ((struct socket *)fp->f_data)->so_pgid;
  303                         return (0);
  304                 }
  305                 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
  306                 *retval = -*retval;
  307                 return (error);
  308 
  309         case F_SETOWN:
  310                 if (fp->f_type == DTYPE_SOCKET) {
  311                         ((struct socket *)fp->f_data)->so_pgid =
  312                             (long)uap->arg;
  313                         return (0);
  314                 }
  315                 if ((long)uap->arg <= 0) {
  316                         uap->arg = (int)(-(long)(uap->arg));
  317                 } else {
  318                         struct proc *p1 = pfind((long)uap->arg);
  319                         if (p1 == 0)
  320                                 return (ESRCH);
  321                         uap->arg = (int)p1->p_pgrp->pg_id;
  322                 }
  323                 return (fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
  324 
  325         case F_SETLKW:
  326                 flg |= F_WAIT;
  327                 /* Fall into F_SETLK */
  328 
  329         case F_SETLK:
  330                 if (fp->f_type != DTYPE_VNODE)
  331                         return (EBADF);
  332                 vp = (struct vnode *)fp->f_data;
  333                 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
  334                 /* Copy in the lock structure */
  335                 error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
  336                     sizeof (fl));
  337                 if (error)
  338                         return (error);
  339                 if (fl.l_whence == SEEK_CUR)
  340                         fl.l_start += fp->f_offset;
  341                 switch (fl.l_type) {
  342 
  343                 case F_RDLCK:
  344                         if ((fp->f_flag & FREAD) == 0)
  345                                 return (EBADF);
  346                         p->p_flag |= P_ADVLOCK;
  347                         return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  348 
  349                 case F_WRLCK:
  350                         if ((fp->f_flag & FWRITE) == 0)
  351                                 return (EBADF);
  352                         p->p_flag |= P_ADVLOCK;
  353                         return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  354 
  355                 case F_UNLCK:
  356                         return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
  357                                 F_POSIX));
  358 
  359                 default:
  360                         return (EINVAL);
  361                 }
  362 
  363         case F_GETLK:
  364                 if (fp->f_type != DTYPE_VNODE)
  365                         return (EBADF);
  366                 vp = (struct vnode *)fp->f_data;
  367                 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
  368                 /* Copy in the lock structure */
  369                 error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
  370                     sizeof (fl));
  371                 if (error)
  372                         return (error);
  373                 if (fl.l_whence == SEEK_CUR)
  374                         fl.l_start += fp->f_offset;
  375                 if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
  376                         return (error);
  377                 return (copyout((caddr_t)&fl, (caddr_t)uap->arg,
  378                     sizeof (fl)));
  379 
  380         case F_PREALLOCATE:
  381                 if (fp->f_type != DTYPE_VNODE)
  382                         return (EBADF);
  383 
  384                 /* make sure that we have write permission */
  385                 if ((fp->f_flag & FWRITE) == 0)
  386                         return (EBADF);
  387 
  388                 error = copyin((caddr_t)uap->arg, (caddr_t)&alloc_struct,
  389                     sizeof (alloc_struct));
  390                 if (error)
  391                         return (error);
  392 
  393                 /* now set the space allocated to 0 */
  394                 alloc_struct.fst_bytesalloc = 0;
  395                 
  396                 /*
  397                  * Do some simple parameter checking
  398                  */
  399 
  400                 /* set up the flags */
  401 
  402                 alloc_flags |= PREALLOCATE;
  403                 
  404                 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
  405                         alloc_flags |= ALLOCATECONTIG;
  406 
  407                 if (alloc_struct.fst_flags & F_ALLOCATEALL)
  408                         alloc_flags |= ALLOCATEALL;
  409 
  410                 /*
  411                  * Do any position mode specific stuff.  The only
  412                  * position mode  supported now is PEOFPOSMODE
  413                  */
  414 
  415                 switch (alloc_struct.fst_posmode) {
  416         
  417                 case F_PEOFPOSMODE:
  418                         if (alloc_struct.fst_offset != 0)
  419                                 return (EINVAL);
  420 
  421                         alloc_flags |= ALLOCATEFROMPEOF;
  422                         break;
  423 
  424                 case F_VOLPOSMODE:
  425                         if (alloc_struct.fst_offset <= 0)
  426                                 return (EINVAL);
  427 
  428                         alloc_flags |= ALLOCATEFROMVOL;
  429                         break;
  430 
  431                 default:
  432                         return(EINVAL);
  433                 }
  434 
  435                 vp = (struct vnode *)fp->f_data;
  436 
  437                 /* lock the vnode and call allocate to get the space */
  438                 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
  439                 if (error)
  440                         return (error);
  441                 error = VOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
  442                                      &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
  443                                      fp->f_cred, p);
  444                 VOP_UNLOCK(vp, 0, p);
  445 
  446                 if (error2 = copyout((caddr_t)&alloc_struct,
  447                                                 (caddr_t)uap->arg,
  448                                                 sizeof (alloc_struct))) {
  449                         if (error)
  450                                 return(error);
  451                         else
  452                                 return(error2);
  453                 }
  454                 return(error);
  455                 
  456         case F_SETSIZE:
  457                 if (fp->f_type != DTYPE_VNODE)
  458                         return (EBADF);
  459                 
  460                 error = copyin((caddr_t)uap->arg, (caddr_t)&offset,
  461                                         sizeof (off_t));
  462                 if (error)
  463                         return (error);
  464 
  465                 /*
  466                  * Make sure that we are root.  Growing a file
  467                  * without zero filling the data is a security hole 
  468                  * root would have access anyway so we'll allow it
  469                  */
  470 
  471                 if (!is_suser())
  472                         return (EACCES);
  473 
  474                 vp = (struct vnode *)fp->f_data;
  475 
  476                 /* lock the vnode and call allocate to get the space */
  477                 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
  478                 if (error)
  479                         return (error);
  480                 error = VOP_TRUNCATE(vp,offset,IO_NOZEROFILL,fp->f_cred,p);
  481                 VOP_UNLOCK(vp,0,p);
  482                 return(error);
  483 
  484         case F_RDAHEAD:
  485                 if (fp->f_type != DTYPE_VNODE)
  486                         return (EBADF);
  487                 vp = (struct vnode *)fp->f_data;
  488 
  489                 simple_lock(&vp->v_interlock);
  490                 if (uap->arg)
  491                         vp->v_flag &= ~VRAOFF;
  492                 else
  493                         vp->v_flag |= VRAOFF;
  494                 simple_unlock(&vp->v_interlock);
  495                 return (0);
  496 
  497         case F_NOCACHE:
  498                 if (fp->f_type != DTYPE_VNODE)
  499                         return (EBADF);
  500                 vp = (struct vnode *)fp->f_data;
  501 
  502                 simple_lock(&vp->v_interlock);
  503                 if (uap->arg)
  504                         vp->v_flag |= VNOCACHE_DATA;
  505                 else
  506                         vp->v_flag &= ~VNOCACHE_DATA;
  507                 simple_unlock(&vp->v_interlock);
  508                 return (0);
  509 
  510         case F_RDADVISE:
  511                 if (fp->f_type != DTYPE_VNODE)
  512                         return (EBADF);
  513                 vp = (struct vnode *)fp->f_data;
  514 
  515                 if (error = copyin((caddr_t)uap->arg,
  516                                         (caddr_t)&ra_struct, sizeof (ra_struct)))
  517                         return(error);
  518                 return (VOP_IOCTL(vp, 1, (caddr_t)&ra_struct, 0, fp->f_cred, p));
  519 
  520         case F_CHKCLEAN:
  521                 /*
  522                  * used by regression test to determine if 
  523                  * all the dirty pages (via write) have been cleaned
  524                  * after a call to 'fsysnc'.
  525                  */
  526                 if (fp->f_type != DTYPE_VNODE)
  527                         return (EBADF);
  528                 vp = (struct vnode *)fp->f_data;
  529 
  530                 return (VOP_IOCTL(vp, 5, 0, 0, fp->f_cred, p));
  531 
  532         case F_READBOOTSTRAP:
  533         case F_WRITEBOOTSTRAP:
  534                 if (fp->f_type != DTYPE_VNODE)
  535                         return (EBADF);
  536 
  537                 error = copyin((caddr_t)uap->arg, (caddr_t)&fbt_struct,
  538                                 sizeof (fbt_struct));
  539                 if (error)
  540                         return (error);
  541 
  542                 if (uap->cmd == F_WRITEBOOTSTRAP) {
  543                   /*
  544                    * Make sure that we are root.  Updating the
  545                    * bootstrap on a disk could be a security hole
  546                    */
  547                         if (!is_suser())
  548                                 return (EACCES);
  549                 }
  550 
  551                 vp = (struct vnode *)fp->f_data;
  552                 if (vp->v_tag != VT_HFS)        /* XXX */
  553                         error = EINVAL;
  554                 else {
  555                         /* lock the vnode and call VOP_IOCTL to handle the I/O */
  556                         error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
  557                         if (error)
  558                                 return (error);
  559                         error = VOP_IOCTL(vp, (uap->cmd == F_WRITEBOOTSTRAP) ? 3 : 2,
  560                                         (caddr_t)&fbt_struct, 0, fp->f_cred, p);
  561                         VOP_UNLOCK(vp,0,p);
  562                 }
  563                 return(error);
  564 
  565         case F_LOG2PHYS:
  566                 if (fp->f_type != DTYPE_VNODE)
  567                         return (EBADF);
  568                 vp = (struct vnode *)fp->f_data;
  569                 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
  570                 if (error)
  571                         return (error);
  572                 error = VOP_OFFTOBLK(vp, fp->f_offset, &lbn);
  573                 if (error)
  574                         return (error);
  575                 error = VOP_BLKTOOFF(vp, lbn, &offset);
  576                 if (error)
  577                         return (error);
  578                 error = VOP_BMAP(vp, lbn, &devvp, &bn, 0);
  579                 VOP_DEVBLOCKSIZE(devvp, &devBlockSize);
  580                 VOP_UNLOCK(vp, 0, p);
  581                 if (!error) {
  582                         l2p_struct.l2p_flags = 0;       /* for now */
  583                         l2p_struct.l2p_contigbytes = 0; /* for now */
  584                         l2p_struct.l2p_devoffset = bn * devBlockSize;
  585                         l2p_struct.l2p_devoffset += fp->f_offset - offset;
  586                         error = copyout((caddr_t)&l2p_struct,
  587                                         (caddr_t)uap->arg,
  588                                         sizeof (l2p_struct));
  589                 }
  590                 return (error);
  591 
  592         case F_GETPATH: {
  593                 char *pathbuf;
  594                 int len;
  595                 extern int vn_getpath(struct vnode *vp, char *pathbuf, int *len);
  596 
  597                 if (fp->f_type != DTYPE_VNODE)
  598                         return (EBADF);
  599                 vp = (struct vnode *)fp->f_data;
  600 
  601                 len = MAXPATHLEN;
  602                 MALLOC(pathbuf, char *, len, M_TEMP, M_WAITOK);
  603                 error = vn_getpath(vp, pathbuf, &len);
  604                 if (error == 0)
  605                         error = copyout((caddr_t)pathbuf, (caddr_t)uap->arg, len);
  606                 FREE(pathbuf, M_TEMP);
  607                 return error;
  608         }
  609 
  610         case F_FULLFSYNC: {
  611                 if (fp->f_type != DTYPE_VNODE)
  612                         return (EBADF);
  613                 vp = (struct vnode *)fp->f_data;
  614 
  615                 return (VOP_IOCTL(vp, 6, (caddr_t)NULL, 0, fp->f_cred, p));
  616         }
  617             
  618         default:
  619                 return (EINVAL);
  620         }
  621         /* NOTREACHED */
  622 }
  623 
  624 /*
  625  * Common code for dup, dup2, and fcntl(F_DUPFD).
  626  */
  627 int
  628 finishdup(fdp, old, new, retval)
  629         register struct filedesc *fdp;
  630         register int old, new;
  631         register_t *retval;
  632 {
  633         register struct file *fp;
  634 
  635         if ((fp = fdp->fd_ofiles[old]) == NULL ||
  636                         (fdp->fd_ofileflags[old] & UF_RESERVED)) {
  637                 _fdrelse(fdp, new);
  638                 return (EBADF);
  639         }
  640         fdp->fd_ofiles[new] = fp;
  641         fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
  642         (void)fref(fp);
  643         if (new > fdp->fd_lastfile)
  644                 fdp->fd_lastfile = new;
  645         *retval = new;
  646         return (0);
  647 }
  648 
  649 /*
  650  * Close a file descriptor.
  651  */
  652 struct close_args {
  653         int     fd;
  654 };
  655 /* ARGSUSED */
  656 int
  657 close(p, uap, retval)
  658         struct proc *p;
  659         struct close_args *uap;
  660         register_t *retval;
  661 {
  662         int fd = uap->fd;
  663         register struct filedesc *fdp = p->p_fd;
  664         register struct file *fp;
  665 
  666         if ((u_int)fd >= fdp->fd_nfiles ||
  667                         (fp = fdp->fd_ofiles[fd]) == NULL ||
  668                         (fdp->fd_ofileflags[fd] & UF_RESERVED))
  669                 return (EBADF);
  670 
  671         /* Keep people from using the filedesc while we are closing it */
  672         fdp->fd_ofileflags[fd] |= UF_RESERVED;
  673                 
  674         /* cancel all async IO requests that can be cancelled. */
  675         _aio_close( p, fd );
  676 
  677         if (fd < fdp->fd_knlistsize)
  678                 knote_fdclose(p, fd);
  679 
  680         _fdrelse(fdp, fd);
  681         return (closef(fp, p));
  682 }
  683 
  684 /*
  685  * Return status information about a file descriptor.
  686  */
  687 struct fstat_args {
  688         int     fd;
  689         struct  stat *sb;
  690 };
  691 /* ARGSUSED */
  692 int
  693 fstat(p, uap, retval)
  694         struct proc *p;
  695         register struct fstat_args *uap;
  696         register_t *retval;
  697 {
  698         int fd = uap->fd;
  699         register struct filedesc *fdp = p->p_fd;
  700         register struct file *fp;
  701         struct stat ub;
  702         int error;
  703 
  704         AUDIT_ARG(fd, uap->fd);
  705         if ((u_int)fd >= fdp->fd_nfiles ||
  706                         (fp = fdp->fd_ofiles[fd]) == NULL ||
  707                         (fdp->fd_ofileflags[fd] & UF_RESERVED))
  708                 return (EBADF);
  709         switch (fp->f_type) {
  710 
  711         case DTYPE_VNODE:
  712                 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
  713                 if (error == 0) {
  714                         AUDIT_ARG(vnpath, (struct vnode *)fp->f_data, ARG_VNODE1);
  715                 }
  716                 break;
  717 
  718         case DTYPE_SOCKET:
  719                 error = soo_stat((struct socket *)fp->f_data, &ub);
  720                 break;
  721 
  722         case DTYPE_PSXSHM:
  723                 error = pshm_stat((void *)fp->f_data, &ub);
  724                 break;
  725 
  726         case DTYPE_KQUEUE:
  727           error = kqueue_stat(fp, &ub, p);
  728           break;
  729 
  730         default:
  731                 panic("fstat");
  732                 /*NOTREACHED*/
  733         }
  734         if (error == 0)
  735                 error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
  736                     sizeof (ub));
  737         return (error);
  738 }
  739 
  740 #if COMPAT_43
  741 /*
  742  * Return status information about a file descriptor.
  743  */
  744 struct ofstat_args {
  745         int     fd;
  746         struct  ostat *sb;
  747 };
  748 /* ARGSUSED */
  749 ofstat(p, uap, retval)
  750         struct proc *p;
  751         register struct ofstat_args *uap;
  752         register_t *retval;
  753 {
  754         int fd = uap->fd;
  755         register struct filedesc *fdp = p->p_fd;
  756         register struct file *fp;
  757         struct stat ub;
  758         struct ostat oub;
  759         int error;
  760 
  761         if ((u_int)fd >= fdp->fd_nfiles ||
  762                         (fp = fdp->fd_ofiles[fd]) == NULL ||
  763                         (fdp->fd_ofileflags[fd] & UF_RESERVED))
  764                 return (EBADF);
  765         switch (fp->f_type) {
  766 
  767         case DTYPE_VNODE:
  768                 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
  769                 break;
  770 
  771         case DTYPE_SOCKET:
  772                 error = soo_stat((struct socket *)fp->f_data, &ub);
  773                 break;
  774 
  775         default:
  776                 panic("ofstat");
  777                 /*NOTREACHED*/
  778         }
  779         cvtstat(&ub, &oub);
  780         if (error == 0)
  781                 error = copyout((caddr_t)&oub, (caddr_t)uap->sb,
  782                     sizeof (oub));
  783         return (error);
  784 }
  785 #endif /* COMPAT_43 */
  786 
  787 /*
  788  * Return pathconf information about a file descriptor.
  789  */
  790 struct fpathconf_args {
  791         int     fd;
  792         int     name;
  793 };
  794 /* ARGSUSED */
  795 fpathconf(p, uap, retval)
  796         struct proc *p;
  797         register struct fpathconf_args *uap;
  798         register_t *retval;
  799 {
  800         int fd = uap->fd;
  801         struct filedesc *fdp = p->p_fd;
  802         struct file *fp;
  803         struct vnode *vp;
  804 
  805         AUDIT_ARG(fd, uap->fd);
  806         if ((u_int)fd >= fdp->fd_nfiles ||
  807                         (fp = fdp->fd_ofiles[fd]) == NULL ||
  808                         (fdp->fd_ofileflags[fd] & UF_RESERVED))
  809                 return (EBADF);
  810         switch (fp->f_type) {
  811 
  812         case DTYPE_SOCKET:
  813                 if (uap->name != _PC_PIPE_BUF)
  814                         return (EINVAL);
  815                 *retval = PIPE_BUF;
  816                 return (0);
  817 
  818         case DTYPE_VNODE:
  819                 vp = (struct vnode *)fp->f_data;
  820                 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
  821 
  822                 return (VOP_PATHCONF(vp, uap->name, retval));
  823 
  824         default:
  825                 panic("fpathconf");
  826         }
  827         /*NOTREACHED*/
  828 }
  829 
  830 /*
  831  * Allocate a file descriptor for the process.
  832  */
  833 int fdexpand;
  834 
  835 int
  836 fdalloc(p, want, result)
  837         struct proc *p;
  838         int want;
  839         int *result;
  840 {
  841         register struct filedesc *fdp = p->p_fd;
  842         register int i;
  843         int lim, last, nfiles, oldnfiles;
  844         struct file **newofiles, **ofiles;
  845         char *newofileflags, *ofileflags;
  846 
  847         /*
  848          * Search for a free descriptor starting at the higher
  849          * of want or fd_freefile.  If that fails, consider
  850          * expanding the ofile array.
  851          */
  852         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
  853         for (;;) {
  854                 last = min(fdp->fd_nfiles, lim);
  855                 if ((i = want) < fdp->fd_freefile)
  856                         i = fdp->fd_freefile;
  857                 ofiles = &fdp->fd_ofiles[i];
  858                 ofileflags = &fdp->fd_ofileflags[i];
  859                 for (; i < last; i++) {
  860                         if (*ofiles == NULL && !(*ofileflags & UF_RESERVED)) {
  861                                 *ofileflags = UF_RESERVED;
  862                                 if (i > fdp->fd_lastfile)
  863                                         fdp->fd_lastfile = i;
  864                                 if (want <= fdp->fd_freefile)
  865                                         fdp->fd_freefile = i;
  866                                 *result = i;
  867                                 return (0);
  868                         }
  869                         ofiles++; ofileflags++;
  870                 }
  871 
  872                 /*
  873                  * No space in current array.  Expand?
  874                  */
  875                 if (fdp->fd_nfiles >= lim)
  876                         return (EMFILE);
  877                 if (fdp->fd_nfiles < NDEXTENT)
  878                         nfiles = NDEXTENT;
  879                 else
  880                         nfiles = 2 * fdp->fd_nfiles;
  881                 /* Enforce lim */
  882                 if (nfiles > lim)
  883                         nfiles = lim;
  884                 MALLOC_ZONE(newofiles, struct file **,
  885                                 nfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
  886                 if (fdp->fd_nfiles >= nfiles) {
  887                         FREE_ZONE(newofiles, nfiles * OFILESIZE, M_OFILETABL);
  888                         continue;
  889                 }
  890                 newofileflags = (char *) &newofiles[nfiles];
  891                 /*
  892                  * Copy the existing ofile and ofileflags arrays
  893                  * and zero the new portion of each array.
  894                  */
  895                 oldnfiles = fdp->fd_nfiles;
  896                 (void) memcpy(newofiles, fdp->fd_ofiles,
  897                                 oldnfiles * sizeof *fdp->fd_ofiles);
  898                 (void) memset(&newofiles[oldnfiles], 0,
  899                                 (nfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
  900 
  901                 (void) memcpy(newofileflags, fdp->fd_ofileflags,
  902                                 oldnfiles * sizeof *fdp->fd_ofileflags);
  903                 (void) memset(&newofileflags[oldnfiles], 0,
  904                                 (nfiles - oldnfiles) *
  905                                                 sizeof *fdp->fd_ofileflags);
  906                 ofiles = fdp->fd_ofiles;
  907                 fdp->fd_ofiles = newofiles;
  908                 fdp->fd_ofileflags = newofileflags;
  909                 fdp->fd_nfiles = nfiles;
  910                 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
  911                 fdexpand++;
  912         }
  913 }
  914 
  915 /*
  916  * Check to see whether n user file descriptors
  917  * are available to the process p.
  918  */
  919 int
  920 fdavail(p, n)
  921         struct proc *p;
  922         register int n;
  923 {
  924         register struct filedesc *fdp = p->p_fd;
  925         register struct file **fpp;
  926         register char *flags;
  927         register int i, lim;
  928 
  929         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
  930         if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
  931                 return (1);
  932         fpp = &fdp->fd_ofiles[fdp->fd_freefile];
  933         flags = &fdp->fd_ofileflags[fdp->fd_freefile];
  934         for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
  935                 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
  936                         return (1);
  937         return (0);
  938 }
  939 
  940 void
  941 fdrelse(p, fd)
  942         struct proc *p;
  943         int fd;
  944 {
  945         _fdrelse(p->p_fd, fd);
  946 }
  947 
  948 int
  949 fdgetf(p, fd, resultfp)
  950         register struct proc *p;
  951         register int fd;
  952         struct file **resultfp;
  953 {
  954         register struct filedesc *fdp = p->p_fd;
  955         struct file *fp;
  956 
  957         if ((u_int)fd >= fdp->fd_nfiles ||
  958                         (fp = fdp->fd_ofiles[fd]) == NULL ||
  959                         (fdp->fd_ofileflags[fd] & UF_RESERVED))
  960                 return (EBADF);
  961 
  962         if (resultfp)
  963                 *resultfp = fp;
  964         return (0);
  965 }
  966 
  967 /*
  968  * Create a new open file structure and allocate
  969  * a file decriptor for the process that refers to it.
  970  */
  971 int
  972 falloc(p, resultfp, resultfd)
  973         register struct proc *p;
  974         struct file **resultfp;
  975         int *resultfd;
  976 {
  977         register struct file *fp, *fq;
  978         int error, i;
  979 
  980         if (error = fdalloc(p, 0, &i))
  981                 return (error);
  982         if (nfiles >= maxfiles) {
  983                 tablefull("file");
  984                 return (ENFILE);
  985         }
  986         /*
  987          * Allocate a new file descriptor.
  988          * If the process has file descriptor zero open, add to the list
  989          * of open files at that point, otherwise put it at the front of
  990          * the list of open files.
  991          */
  992         nfiles++;
  993         MALLOC_ZONE(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
  994         bzero(fp, sizeof(struct file));
  995         p->p_fd->fd_ofiles[i] = fp;
  996         fp->f_count = 1;
  997         fp->f_cred = p->p_ucred;
  998         crhold(fp->f_cred);
  999         if (resultfp)
 1000                 *resultfp = fp;
 1001         if (resultfd)
 1002                 *resultfd = i;
 1003         if (fq = p->p_fd->fd_ofiles[0]) {
 1004                 LIST_INSERT_AFTER(fq, fp, f_list);
 1005         } else {
 1006                 LIST_INSERT_HEAD(&filehead, fp, f_list);
 1007         }
 1008         return (0);
 1009 }
 1010 
 1011 /*
 1012  * Free a file structure.
 1013  */
 1014 void
 1015 ffree(fp)
 1016         register struct file *fp;
 1017 {
 1018         register struct file *fq;
 1019         struct ucred *cred;
 1020 
 1021         LIST_REMOVE(fp, f_list);
 1022         cred = fp->f_cred;
 1023         if (cred != NOCRED) {
 1024                 fp->f_cred = NOCRED;
 1025                 crfree(cred);
 1026         }
 1027 
 1028         nfiles--;
 1029         memset(fp, 0xff, sizeof *fp);
 1030         fp->f_count = (short)0xffff;
 1031 
 1032         FREE_ZONE(fp, sizeof *fp, M_FILE);
 1033 }
 1034 
 1035 void
 1036 fdexec(p)
 1037         struct proc *p;
 1038 {
 1039         register struct filedesc *fdp = p->p_fd;
 1040         register int i = fdp->fd_lastfile;
 1041         register struct file **fpp = &fdp->fd_ofiles[i];
 1042         register char *flags = &fdp->fd_ofileflags[i];
 1043 
 1044         while (i >= 0) {
 1045                 if ((*flags & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
 1046                         register struct file *fp = *fpp;
 1047 
 1048                         if (i < fdp->fd_knlistsize)
 1049                                 knote_fdclose(p, i);
 1050 
 1051                         *fpp = NULL; *flags = 0;
 1052                         if (i == fdp->fd_lastfile && i > 0)
 1053                                 fdp->fd_lastfile--;
 1054                         closef(fp, p);
 1055                 }
 1056                 else
 1057                         *flags &= ~UF_MAPPED;
 1058 
 1059                 i--; fpp--; flags--;
 1060         }
 1061 }
 1062 
 1063 /*
 1064  * Copy a filedesc structure.
 1065  */
 1066 struct filedesc *
 1067 fdcopy(p)
 1068         struct proc *p;
 1069 {
 1070         register struct filedesc *newfdp, *fdp = p->p_fd;
 1071         register int i;
 1072 
 1073         MALLOC_ZONE(newfdp, struct filedesc *,
 1074                         sizeof *newfdp, M_FILEDESC, M_WAITOK);
 1075         (void) memcpy(newfdp, fdp, sizeof *newfdp);
 1076         VREF(newfdp->fd_cdir);
 1077         if (newfdp->fd_rdir)
 1078                 VREF(newfdp->fd_rdir);
 1079         newfdp->fd_refcnt = 1;
 1080 
 1081         /*
 1082          * If the number of open files fits in the internal arrays
 1083          * of the open file structure, use them, otherwise allocate
 1084          * additional memory for the number of descriptors currently
 1085          * in use.
 1086          */
 1087         if (newfdp->fd_lastfile < NDFILE)
 1088                 i = NDFILE;
 1089         else {
 1090                 /*
 1091                  * Compute the smallest multiple of NDEXTENT needed
 1092                  * for the file descriptors currently in use,
 1093                  * allowing the table to shrink.
 1094                  */
 1095                 i = newfdp->fd_nfiles;
 1096                 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
 1097                         i /= 2;
 1098         }
 1099         MALLOC_ZONE(newfdp->fd_ofiles, struct file **,
 1100                                 i * OFILESIZE, M_OFILETABL, M_WAITOK);
 1101         newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
 1102         newfdp->fd_nfiles = i;
 1103         if (fdp->fd_nfiles > 0) {
 1104                 register struct file **fpp;
 1105                 register char *flags;
 1106 
 1107                 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
 1108                                         i * sizeof *fdp->fd_ofiles);
 1109                 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
 1110                                         i * sizeof *fdp->fd_ofileflags);
 1111 
 1112                 /*
 1113                  * kq descriptors cannot be copied.
 1114                  */
 1115                 if (newfdp->fd_knlistsize != -1) {
 1116                         fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
 1117                         for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
 1118                                 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
 1119                                         *fpp = NULL;
 1120                                         if (i < newfdp->fd_freefile)
 1121                                                 newfdp->fd_freefile = i;
 1122                                 }
 1123                                 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
 1124                                         newfdp->fd_lastfile--;
 1125                         }
 1126                         newfdp->fd_knlist = NULL;
 1127                         newfdp->fd_knlistsize = -1;
 1128                         newfdp->fd_knhash = NULL;
 1129                         newfdp->fd_knhashmask = 0;
 1130                 }
 1131 
 1132                 fpp = newfdp->fd_ofiles;
 1133                 flags = newfdp->fd_ofileflags;
 1134                 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++, flags++)
 1135                         if (*fpp != NULL && !(*flags & UF_RESERVED)) {
 1136                                 (void)fref(*fpp);
 1137                         } else {
 1138                                 *fpp = NULL;
 1139                                 *flags = 0;
 1140                         }
 1141         } else
 1142                 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
 1143 
 1144         return (newfdp);
 1145 }
 1146 
 1147 /*
 1148  * Release a filedesc structure.
 1149  */
 1150 void
 1151 fdfree(p)
 1152         struct proc *p;
 1153 {
 1154         struct filedesc *fdp;
 1155         struct file *fp;
 1156         int i;
 1157         struct vnode *tvp;
 1158 
 1159         /* Certain daemons might not have file descriptors */
 1160         if ((fdp = p->p_fd) == NULL)
 1161                 return;
 1162 
 1163         if (--fdp->fd_refcnt > 0)
 1164                 return;
 1165 
 1166         /* Last reference: the structure can't change out from under us */
 1167         if (fdp->fd_nfiles > 0) {
 1168                 for (i = fdp->fd_lastfile; i >= 0; i--)
 1169 #if 1   /* WORKAROUND */
 1170                         /*
 1171                          * Merlot: need to remove the bogus f_data check
 1172                          * from the following "if" statement.  It's there
 1173                          * because of the network/kernel funnel race on a
 1174                          * close of a socket vs. fdfree on exit.  See
 1175                          * Radar rdar://problem/3365650 for details, but
 1176                          * the sort version is the commment before the "if"
 1177                          * above is wrong under certain circumstances.
 1178                          *
 1179                          * We have to do this twice, in case knote_fdclose()
 1180                          * results in a block.
 1181                          *
 1182                          * This works because an fdfree() will set all fields
 1183                          * in the struct file to -1.
 1184                          */
 1185                         if ((fp = fdp->fd_ofiles[i]) != NULL &&
 1186                                 fp->f_data != (caddr_t)-1) {
 1187                                 if (i < fdp->fd_knlistsize)
 1188                                         knote_fdclose(p, i);
 1189                                 if (fp->f_data != (caddr_t)-1)
 1190                                         (void) closef(fp, p);
 1191                         }
 1192 #else   /* !WORKAROUND */
 1193                         if ((fp = fdp->fd_ofiles[i]) != NULL) {
 1194                                 if (i < fdp->fd_knlistsize)
 1195                                         knote_fdclose(p, i);
 1196                                 (void) closef(fp, p);
 1197                         }
 1198 #endif  /* !WORKAROUND */
 1199                 FREE_ZONE(fdp->fd_ofiles,
 1200                                 fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
 1201         }
 1202 
 1203         tvp = fdp->fd_cdir;
 1204         fdp->fd_cdir = NULL;
 1205         vrele(tvp);
 1206 
 1207         if (fdp->fd_rdir) {
 1208                 tvp = fdp->fd_rdir;
 1209                 fdp->fd_rdir = NULL;
 1210                 vrele(tvp);
 1211         }
 1212 
 1213         if (fdp->fd_knlist)
 1214                 FREE(fdp->fd_knlist, M_KQUEUE);
 1215         if (fdp->fd_knhash)
 1216                 FREE(fdp->fd_knhash, M_KQUEUE);
 1217 
 1218         FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
 1219 }
 1220 
 1221 static int
 1222 closef_finish(fp, p)
 1223         register struct file *fp;
 1224         register struct proc *p;
 1225 {
 1226         struct vnode *vp;
 1227         struct flock lf;
 1228         int error;
 1229 
 1230         if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
 1231                 lf.l_whence = SEEK_SET;
 1232                 lf.l_start = 0;
 1233                 lf.l_len = 0;
 1234                 lf.l_type = F_UNLCK;
 1235                 vp = (struct vnode *)fp->f_data;
 1236                 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
 1237         }
 1238         if (fp->f_ops)
 1239                 error = fo_close(fp, p);
 1240         else
 1241                 error = 0;
 1242         ffree(fp);
 1243         return (error);
 1244 }
 1245 
 1246 /*
 1247  * Internal form of close.
 1248  * Decrement reference count on file structure.
 1249  * Note: p may be NULL when closing a file
 1250  * that was being passed in a message.
 1251  */
 1252 int
 1253 closef(fp, p)
 1254         register struct file *fp;
 1255         register struct proc *p;
 1256 {
 1257         struct vnode *vp;
 1258         struct flock lf;
 1259         int error;
 1260 
 1261         if (fp == NULL)
 1262                 return (0);
 1263         /*
 1264          * POSIX record locking dictates that any close releases ALL
 1265          * locks owned by this process.  This is handled by setting
 1266          * a flag in the unlock to free ONLY locks obeying POSIX
 1267          * semantics, and not to free BSD-style file locks.
 1268          * If the descriptor was in a message, POSIX-style locks
 1269          * aren't passed with the descriptor.
 1270          */
 1271         if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
 1272                 lf.l_whence = SEEK_SET;
 1273                 lf.l_start = 0;
 1274                 lf.l_len = 0;
 1275                 lf.l_type = F_UNLCK;
 1276                 vp = (struct vnode *)fp->f_data;
 1277                 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
 1278         }
 1279         if (frele_internal(fp) > 0)
 1280                 return (0);
 1281         return(closef_finish(fp, p));
 1282 }
 1283 
 1284 /*
 1285  * Apply an advisory lock on a file descriptor.
 1286  *
 1287  * Just attempt to get a record lock of the requested type on
 1288  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
 1289  */
 1290 struct flock_args {
 1291         int     fd;
 1292         int     how;
 1293 };
 1294 /* ARGSUSED */
 1295 int
 1296 flock(p, uap, retval)
 1297         struct proc *p;
 1298         register struct flock_args *uap;
 1299         register_t *retval;
 1300 {
 1301         int fd = uap->fd;
 1302         int how = uap->how;
 1303         register struct filedesc *fdp = p->p_fd;
 1304         register struct file *fp;
 1305         struct vnode *vp;
 1306         struct flock lf;
 1307 
 1308         AUDIT_ARG(fd, uap->fd);
 1309         if ((u_int)fd >= fdp->fd_nfiles ||
 1310                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 1311                         (fdp->fd_ofileflags[fd] & UF_RESERVED))
 1312                 return (EBADF);
 1313         if (fp->f_type != DTYPE_VNODE)
 1314                 return (EOPNOTSUPP);
 1315         vp = (struct vnode *)fp->f_data;
 1316         AUDIT_ARG(vnpath, vp, ARG_VNODE1);
 1317         lf.l_whence = SEEK_SET;
 1318         lf.l_start = 0;
 1319         lf.l_len = 0;
 1320         if (how & LOCK_UN) {
 1321                 lf.l_type = F_UNLCK;
 1322                 fp->f_flag &= ~FHASLOCK;
 1323                 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
 1324         }
 1325         if (how & LOCK_EX)
 1326                 lf.l_type = F_WRLCK;
 1327         else if (how & LOCK_SH)
 1328                 lf.l_type = F_RDLCK;
 1329         else
 1330                 return (EBADF);
 1331         fp->f_flag |= FHASLOCK;
 1332         if (how & LOCK_NB)
 1333                 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
 1334         return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
 1335 }
 1336 
 1337 /*
 1338  * File Descriptor pseudo-device driver (/dev/fd/).
 1339  *
 1340  * Opening minor device N dup()s the file (if any) connected to file
 1341  * descriptor N belonging to the calling process.  Note that this driver
 1342  * consists of only the ``open()'' routine, because all subsequent
 1343  * references to this file will be direct to the other driver.
 1344  */
 1345 /* ARGSUSED */
 1346 int
 1347 fdopen(dev, mode, type, p)
 1348         dev_t dev;
 1349         int mode, type;
 1350         struct proc *p;
 1351 {
 1352 
 1353         /*
 1354          * XXX Kludge: set curproc->p_dupfd to contain the value of the
 1355          * the file descriptor being sought for duplication. The error 
 1356          * return ensures that the vnode for this device will be released
 1357          * by vn_open. Open will detect this special error and take the
 1358          * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
 1359          * will simply report the error.
 1360          */
 1361         p->p_dupfd = minor(dev);
 1362         return (ENODEV);
 1363 }
 1364 
 1365 /*
 1366  * Duplicate the specified descriptor to a free descriptor.
 1367  */
 1368 int
 1369 dupfdopen(fdp, indx, dfd, mode, error)
 1370         register struct filedesc *fdp;
 1371         register int indx, dfd;
 1372         int mode;
 1373         int error;
 1374 {
 1375         register struct file *wfp;
 1376         struct file *fp;
 1377 
 1378         /*
 1379          * If the to-be-dup'd fd number is greater than the allowed number
 1380          * of file descriptors, or the fd to be dup'd has already been
 1381          * closed, reject.  Note, check for new == old is necessary as
 1382          * falloc could allocate an already closed to-be-dup'd descriptor
 1383          * as the new descriptor.
 1384          */
 1385         fp = fdp->fd_ofiles[indx];
 1386         if ((u_int)dfd >= fdp->fd_nfiles ||
 1387                         (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
 1388                         (fdp->fd_ofileflags[dfd] & UF_RESERVED))
 1389                 return (EBADF);
 1390 
 1391         /*
 1392          * There are two cases of interest here.
 1393          *
 1394          * For ENODEV simply dup (dfd) to file descriptor
 1395          * (indx) and return.
 1396          *
 1397          * For ENXIO steal away the file structure from (dfd) and
 1398          * store it in (indx).  (dfd) is effectively closed by
 1399          * this operation.
 1400          *
 1401          * Any other error code is just returned.
 1402          */
 1403         switch (error) {
 1404         case ENODEV:
 1405                 /*
 1406                  * Check that the mode the file is being opened for is a
 1407                  * subset of the mode of the existing descriptor.
 1408                  */
 1409                 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
 1410                         return (EACCES);
 1411                 (void)fref(wfp);
 1412                 if (indx > fdp->fd_lastfile)
 1413                         fdp->fd_lastfile = indx;;
 1414                 fdp->fd_ofiles[indx] = wfp;
 1415                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 1416                 return (0);
 1417 
 1418         case ENXIO:
 1419                 /*
 1420                  * Steal away the file pointer from dfd, and stuff it into indx.
 1421                  */
 1422                 if (indx > fdp->fd_lastfile)
 1423                         fdp->fd_lastfile = indx;;
 1424                 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
 1425                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 1426                 _fdrelse(fdp, dfd);
 1427                 return (0);
 1428 
 1429         default:
 1430                 return (error);
 1431         }
 1432         /* NOTREACHED */
 1433 }
 1434 
 1435 /* Reference manipulation routines for the file structure */
 1436 
 1437 int
 1438 fref(struct file *fp)
 1439 {
 1440         if (fp->f_count == (short)0xffff)
 1441                 return (-1);
 1442         if (++fp->f_count <= 0)
 1443                 panic("fref: f_count");
 1444         return ((int)fp->f_count);
 1445 }
 1446 
 1447 static int 
 1448 frele_internal(struct file *fp)
 1449 {
 1450         if (fp->f_count == (short)0xffff)
 1451                 panic("frele: stale");
 1452         if (--fp->f_count < 0)
 1453                 panic("frele: count < 0");
 1454         return ((int)fp->f_count);
 1455 }
 1456 
 1457 
 1458 int
 1459 frele(struct file *fp)
 1460 {
 1461         int count;
 1462         funnel_t * fnl;
 1463         extern int disable_funnel;
 1464 
 1465         fnl = thread_funnel_get();
 1466         /*
 1467          * If the funnels are merged then atleast a funnel should be held
 1468          * else frele should come in with kernel funnel only
 1469          */
 1470         if (!disable_funnel && (fnl != kernel_flock)) {
 1471                 panic("frele: kernel funnel not held");
 1472 
 1473         } else if  (fnl == THR_FUNNEL_NULL) {
 1474                 panic("frele: no funnel held");
 1475         }
 1476 
 1477         if ((count = frele_internal(fp)) == 0) {
 1478                 /* some one closed the fd while we were blocked */
 1479                 (void)closef_finish(fp, current_proc());
 1480         }
 1481         return(count);
 1482 }
 1483 
 1484 int
 1485 fcount(struct file *fp)
 1486 {
 1487         if (fp->f_count == (short)0xffff)
 1488                 panic("fcount: stale");
 1489         return ((int)fp->f_count);
 1490 }
 1491 

Cache object: 0f1b1f7655120ea964a6b3ae053b3a99


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