home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / kern_descrip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  18.3 KB  |  762 lines

  1. /*
  2.  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)kern_descrip.c    7.28 (Berkeley) 6/25/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "filedesc.h"
  39. #include "kernel.h"
  40. #include "vnode.h"
  41. #include "proc.h"
  42. #include "file.h"
  43. #include "socket.h"
  44. #include "socketvar.h"
  45. #include "stat.h"
  46. #include "ioctl.h"
  47. #include "fcntl.h"
  48. #include "malloc.h"
  49. #include "syslog.h"
  50. #include "resourcevar.h"
  51.  
  52. /*
  53.  * Descriptor management.
  54.  */
  55. struct file *filehead;    /* head of list of open files */
  56. int nfiles;        /* actual number of open files */
  57.  
  58. /*
  59.  * System calls on descriptors.
  60.  */
  61. /* ARGSUSED */
  62. getdtablesize(p, uap, retval)
  63.     struct proc *p;
  64.     struct args *uap;
  65.     int *retval;
  66. {
  67.  
  68.     *retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
  69.     return (0);
  70. }
  71.  
  72. /*
  73.  * Duplicate a file descriptor.
  74.  */
  75. /* ARGSUSED */
  76. dup(p, uap, retval)
  77.     struct proc *p;
  78.     struct args {
  79.         int    i;
  80.     } *uap;
  81.     int *retval;
  82. {
  83.     register struct filedesc *fdp = p->p_fd;
  84.     struct file *fp;
  85.     int fd, error;
  86.  
  87.     /*
  88.      * XXX Compatibility
  89.      */
  90.     if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); }
  91.  
  92.     if ((unsigned)uap->i >= fdp->fd_nfiles ||
  93.         (fp = fdp->fd_ofiles[uap->i]) == NULL)
  94.         return (EBADF);
  95.     if (error = fdalloc(p, 0, &fd))
  96.         return (error);
  97.     fdp->fd_ofiles[fd] = fp;
  98.     fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE;
  99.     fp->f_count++;
  100.     if (fd > fdp->fd_lastfile)
  101.         fdp->fd_lastfile = fd;
  102.     *retval = fd;
  103.     return (0);
  104. }
  105.  
  106. /*
  107.  * Duplicate a file descriptor to a particular value.
  108.  */
  109. /* ARGSUSED */
  110. dup2(p, uap, retval)
  111.     struct proc *p;
  112.     struct args {
  113.         u_int    from;
  114.         u_int    to;
  115.     } *uap;
  116.     int *retval;
  117. {
  118.     register struct filedesc *fdp = p->p_fd;
  119.     register struct file *fp;
  120.     register u_int old = uap->from, new = uap->to;
  121.     int i, error;
  122.  
  123.     if (old >= fdp->fd_nfiles ||
  124.         (fp = fdp->fd_ofiles[old]) == NULL ||
  125.         new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
  126.         return (EBADF);
  127.     *retval = new;
  128.     if (old == new)
  129.         return (0);
  130.     if (new >= fdp->fd_nfiles) {
  131.         if (error = fdalloc(p, new, &i))
  132.             return (error);
  133.         if (new != i)
  134.             panic("dup2: fdalloc");
  135.     } else if (fdp->fd_ofiles[new]) {
  136.         if (fdp->fd_ofileflags[new] & UF_MAPPED)
  137.             (void) munmapfd(p, new);
  138.         /*
  139.          * dup2() must succeed even if the close has an error.
  140.          */
  141.         (void) closef(fdp->fd_ofiles[new], p);
  142.     }
  143.     fdp->fd_ofiles[new] = fp;
  144.     fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
  145.     fp->f_count++;
  146.     if (new > fdp->fd_lastfile)
  147.         fdp->fd_lastfile = new;
  148.     return (0);
  149. }
  150.  
  151. /*
  152.  * The file control system call.
  153.  */
  154. /* ARGSUSED */
  155. fcntl(p, uap, retval)
  156.     struct proc *p;
  157.     register struct args {
  158.         int    fd;
  159.         int    cmd;
  160.         int    arg;
  161.     } *uap;
  162.     int *retval;
  163. {
  164.     register struct filedesc *fdp = p->p_fd;
  165.     register struct file *fp;
  166.     register char *pop;
  167.     struct vnode *vp;
  168.     int i, tmp, error, flg = F_POSIX;
  169.     struct flock fl;
  170.  
  171.     if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  172.         (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  173.         return (EBADF);
  174.     pop = &fdp->fd_ofileflags[uap->fd];
  175.     switch(uap->cmd) {
  176.     case F_DUPFD:
  177.         if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
  178.             return (EINVAL);
  179.         if (error = fdalloc(p, uap->arg, &i))
  180.             return (error);
  181.         fdp->fd_ofiles[i] = fp;
  182.         fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE;
  183.         fp->f_count++;
  184.         if (i > fdp->fd_lastfile)
  185.             fdp->fd_lastfile = i;
  186.         *retval = i;
  187.         return (0);
  188.  
  189.     case F_GETFD:
  190.         *retval = *pop & 1;
  191.         return (0);
  192.  
  193.     case F_SETFD:
  194.         *pop = (*pop &~ 1) | (uap->arg & 1);
  195.         return (0);
  196.  
  197.     case F_GETFL:
  198.         *retval = OFLAGS(fp->f_flag);
  199.         return (0);
  200.  
  201.     case F_SETFL:
  202.         fp->f_flag &= ~FCNTLFLAGS;
  203.         fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
  204.         tmp = fp->f_flag & FNONBLOCK;
  205.         error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  206.         if (error)
  207.             return (error);
  208.         tmp = fp->f_flag & FASYNC;
  209.         error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
  210.         if (!error)
  211.             return (0);
  212.         fp->f_flag &= ~FNONBLOCK;
  213.         tmp = 0;
  214.         (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  215.         return (error);
  216.  
  217.     case F_GETOWN:
  218.         if (fp->f_type == DTYPE_SOCKET) {
  219.             *retval = ((struct socket *)fp->f_data)->so_pgid;
  220.             return (0);
  221.         }
  222.         error = (*fp->f_ops->fo_ioctl)
  223.             (fp, (int)TIOCGPGRP, (caddr_t)retval, p);
  224.         *retval = -*retval;
  225.         return (error);
  226.  
  227.     case F_SETOWN:
  228.         if (fp->f_type == DTYPE_SOCKET) {
  229.             ((struct socket *)fp->f_data)->so_pgid = uap->arg;
  230.             return (0);
  231.         }
  232.         if (uap->arg <= 0) {
  233.             uap->arg = -uap->arg;
  234.         } else {
  235.             struct proc *p1 = pfind(uap->arg);
  236.             if (p1 == 0)
  237.                 return (ESRCH);
  238.             uap->arg = p1->p_pgrp->pg_id;
  239.         }
  240.         return ((*fp->f_ops->fo_ioctl)
  241.             (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
  242.  
  243.     case F_SETLKW:
  244.         flg |= F_WAIT;
  245.         /* Fall into F_SETLK */
  246.  
  247.     case F_SETLK:
  248.         if (fp->f_type != DTYPE_VNODE)
  249.             return (EBADF);
  250.         vp = (struct vnode *)fp->f_data;
  251.         /* Copy in the lock structure */
  252.         error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
  253.         if (error)
  254.             return (error);
  255.         if (fl.l_whence == SEEK_CUR)
  256.             fl.l_start += fp->f_offset;
  257.         switch (fl.l_type) {
  258.  
  259.         case F_RDLCK:
  260.             if ((fp->f_flag & FREAD) == 0)
  261.                 return (EBADF);
  262.             p->p_flag |= SADVLCK;
  263.             return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  264.  
  265.         case F_WRLCK:
  266.             if ((fp->f_flag & FWRITE) == 0)
  267.                 return (EBADF);
  268.             p->p_flag |= SADVLCK;
  269.             return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
  270.  
  271.         case F_UNLCK:
  272.             return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
  273.                 F_POSIX));
  274.  
  275.         default:
  276.             return (EINVAL);
  277.         }
  278.  
  279.     case F_GETLK:
  280.         if (fp->f_type != DTYPE_VNODE)
  281.             return (EBADF);
  282.         vp = (struct vnode *)fp->f_data;
  283.         /* Copy in the lock structure */
  284.         error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
  285.         if (error)
  286.             return (error);
  287.         if (fl.l_whence == SEEK_CUR)
  288.             fl.l_start += fp->f_offset;
  289.         if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
  290.             return (error);
  291.         return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
  292.  
  293.     default:
  294.         return (EINVAL);
  295.     }
  296.     /* NOTREACHED */
  297. }
  298.  
  299. /*
  300.  * Close a file descriptor.
  301.  */
  302. /* ARGSUSED */
  303. close(p, uap, retval)
  304.     struct proc *p;
  305.     struct args {
  306.         int    fd;
  307.     } *uap;
  308.     int *retval;
  309. {
  310.     register struct filedesc *fdp = p->p_fd;
  311.     register struct file *fp;
  312.     register int fd = uap->fd;
  313.     register u_char *pf;
  314.  
  315.     if ((unsigned)fd >= fdp->fd_nfiles ||
  316.         (fp = fdp->fd_ofiles[fd]) == NULL)
  317.         return (EBADF);
  318.     pf = (u_char *)&fdp->fd_ofileflags[fd];
  319.     if (*pf & UF_MAPPED)
  320.         (void) munmapfd(p, fd);
  321.     fdp->fd_ofiles[fd] = NULL;
  322.     while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
  323.         fdp->fd_lastfile--;
  324.     if (fd < fdp->fd_freefile)
  325.         fdp->fd_freefile = fd;
  326.     *pf = 0;
  327.     return (closef(fp, p));
  328. }
  329.  
  330. /*
  331.  * Return status information about a file descriptor.
  332.  */
  333. /* ARGSUSED */
  334. fstat(p, uap, retval)
  335.     struct proc *p;
  336.     register struct args {
  337.         int    fd;
  338.         struct    stat *sb;
  339.     } *uap;
  340.     int *retval;
  341. {
  342.     register struct filedesc *fdp = p->p_fd;
  343.     register struct file *fp;
  344.     struct stat ub;
  345.     int error;
  346.  
  347.     if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  348.         (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  349.         return (EBADF);
  350.     switch (fp->f_type) {
  351.  
  352.     case DTYPE_VNODE:
  353.         error = vn_stat((struct vnode *)fp->f_data, &ub, p);
  354.         break;
  355.  
  356.     case DTYPE_SOCKET:
  357.         error = soo_stat((struct socket *)fp->f_data, &ub);
  358.         break;
  359.  
  360.     default:
  361.         panic("fstat");
  362.         /*NOTREACHED*/
  363.     }
  364.     if (error == 0)
  365.         error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
  366.     return (error);
  367. }
  368.  
  369. /*
  370.  * Allocate a file descriptor for the process.
  371.  */
  372. int fdexpand;
  373.  
  374. fdalloc(p, want, result)
  375.     struct proc *p;
  376.     int want;
  377.     int *result;
  378. {
  379.     register struct filedesc *fdp = p->p_fd;
  380.     register int i;
  381.     int lim, last, nfiles;
  382.     struct file **newofile;
  383.     char *newofileflags;
  384.  
  385.     /*
  386.      * Search for a free descriptor starting at the higher
  387.      * of want or fd_freefile.  If that fails, consider
  388.      * expanding the ofile array.
  389.      */
  390.     lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
  391.     for (;;) {
  392.         last = min(fdp->fd_nfiles, lim);
  393.         if ((i = want) < fdp->fd_freefile)
  394.             i = fdp->fd_freefile;
  395.         for (; i < last; i++) {
  396.             if (fdp->fd_ofiles[i] == NULL) {
  397.                 fdp->fd_ofileflags[i] = 0;
  398.                 if (i > fdp->fd_lastfile)
  399.                     fdp->fd_lastfile = i;
  400.                 if (want <= fdp->fd_freefile)
  401.                     fdp->fd_freefile = i;
  402.                 *result = i;
  403.                 return (0);
  404.             }
  405.         }
  406.  
  407.         /*
  408.          * No space in current array.  Expand?
  409.          */
  410.         if (fdp->fd_nfiles >= lim)
  411.             return (EMFILE);
  412.         if (fdp->fd_nfiles < NDEXTENT)
  413.             nfiles = NDEXTENT;
  414.         else
  415.             nfiles = 2 * fdp->fd_nfiles;
  416.         MALLOC(newofile, struct file **, nfiles * OFILESIZE,
  417.             M_FILEDESC, M_WAITOK);
  418.         newofileflags = (char *) &newofile[nfiles];
  419.         /*
  420.          * Copy the existing ofile and ofileflags arrays
  421.          * and zero the new portion of each array.
  422.          */
  423.         bcopy(fdp->fd_ofiles, newofile,
  424.             (i = sizeof(struct file *) * fdp->fd_nfiles));
  425.         bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
  426.         bcopy(fdp->fd_ofileflags, newofileflags,
  427.             (i = sizeof(char) * fdp->fd_nfiles));
  428.         bzero(newofileflags + i, nfiles * sizeof(char) - i);
  429.         if (fdp->fd_nfiles > NDFILE)
  430.             FREE(fdp->fd_ofiles, M_FILEDESC);
  431.         fdp->fd_ofiles = newofile;
  432.         fdp->fd_ofileflags = newofileflags;
  433.         fdp->fd_nfiles = nfiles;
  434.         fdexpand++;
  435.     }
  436. }
  437.  
  438. /*
  439.  * Check to see whether n user file descriptors
  440.  * are available to the process p.
  441.  */
  442. fdavail(p, n)
  443.     struct proc *p;
  444.     register int n;
  445. {
  446.     register struct filedesc *fdp = p->p_fd;
  447.     register struct file **fpp;
  448.     register int i;
  449.  
  450.     if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 &&
  451.         (n -= i) <= 0)
  452.         return (1);
  453.     fpp = &fdp->fd_ofiles[fdp->fd_freefile];
  454.     for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
  455.         if (*fpp == NULL && --n <= 0)
  456.             return (1);
  457.     return (0);
  458. }
  459.  
  460. /*
  461.  * Create a new open file structure and allocate
  462.  * a file decriptor for the process that refers to it.
  463.  */
  464. falloc(p, resultfp, resultfd)
  465.     register struct proc *p;
  466.     struct file **resultfp;
  467.     int *resultfd;
  468. {
  469.     register struct file *fp, *fq, **fpp;
  470.     int error, i;
  471.  
  472.     if (error = fdalloc(p, 0, &i))
  473.         return (error);
  474.     if (nfiles >= maxfiles) {
  475.         tablefull("file");
  476.         return (ENFILE);
  477.     }
  478.     /*
  479.      * Allocate a new file descriptor.
  480.      * If the process has file descriptor zero open, add to the list
  481.      * of open files at that point, otherwise put it at the front of
  482.      * the list of open files.
  483.      */
  484.     nfiles++;
  485.     MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
  486.     if (fq = p->p_fd->fd_ofiles[0])
  487.         fpp = &fq->f_filef;
  488.     else
  489.         fpp = &filehead;
  490.     p->p_fd->fd_ofiles[i] = fp;
  491.     if (fq = *fpp)
  492.         fq->f_fileb = &fp->f_filef;
  493.     fp->f_filef = fq;
  494.     fp->f_fileb = fpp;
  495.     *fpp = fp;
  496.     fp->f_count = 1;
  497.     fp->f_msgcount = 0;
  498.     fp->f_offset = 0;
  499.     fp->f_cred = p->p_ucred;
  500.     crhold(fp->f_cred);
  501.     if (resultfp)
  502.         *resultfp = fp;
  503.     if (resultfd)
  504.         *resultfd = i;
  505.     return (0);
  506. }
  507.  
  508. /*
  509.  * Free a file descriptor.
  510.  */
  511. ffree(fp)
  512.     register struct file *fp;
  513. {
  514.     register struct file *fq;
  515.  
  516.     if (fq = fp->f_filef)
  517.         fq->f_fileb = fp->f_fileb;
  518.     *fp->f_fileb = fq;
  519.     crfree(fp->f_cred);
  520. #ifdef DIAGNOSTIC
  521.     fp->f_filef = NULL;
  522.     fp->f_fileb = NULL;
  523.     fp->f_count = 0;
  524. #endif
  525.     nfiles--;
  526.     FREE(fp, M_FILE);
  527. }
  528.  
  529. /*
  530.  * Copy a filedesc structure.
  531.  */
  532. struct filedesc *
  533. fdcopy(p)
  534.     struct proc *p;
  535. {
  536.     register struct filedesc *newfdp, *fdp = p->p_fd;
  537.     register struct file **fpp;
  538.     register int i;
  539.  
  540.     MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
  541.         M_FILEDESC, M_WAITOK);
  542.     bcopy(fdp, newfdp, sizeof(struct filedesc));
  543.     VREF(newfdp->fd_cdir);
  544.     if (newfdp->fd_rdir)
  545.         VREF(newfdp->fd_rdir);
  546.     newfdp->fd_refcnt = 1;
  547.  
  548.     /*
  549.      * If the number of open files fits in the internal arrays
  550.      * of the open file structure, use them, otherwise allocate
  551.      * additional memory for the number of descriptors currently
  552.      * in use.
  553.      */
  554.     if (newfdp->fd_lastfile < NDFILE) {
  555.         newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
  556.         newfdp->fd_ofileflags =
  557.             ((struct filedesc0 *) newfdp)->fd_dfileflags;
  558.         i = NDFILE;
  559.     } else {
  560.         /*
  561.          * Compute the smallest multiple of NDEXTENT needed
  562.          * for the file descriptors currently in use,
  563.          * allowing the table to shrink.
  564.          */
  565.         i = newfdp->fd_nfiles;
  566.         while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
  567.             i /= 2;
  568.         MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
  569.             M_FILEDESC, M_WAITOK);
  570.         newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
  571.     }
  572.     newfdp->fd_nfiles = i;
  573.     bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
  574.     bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
  575.     fpp = newfdp->fd_ofiles;
  576.     for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
  577.         if (*fpp != NULL)
  578.             (*fpp)->f_count++;
  579.     return (newfdp);
  580. }
  581.  
  582. /*
  583.  * Release a filedesc structure.
  584.  */
  585. void
  586. fdfree(p)
  587.     struct proc *p;
  588. {
  589.     register struct filedesc *fdp = p->p_fd;
  590.     struct file **fpp;
  591.     register int i;
  592.  
  593.     if (--fdp->fd_refcnt > 0)
  594.         return;
  595.     fpp = fdp->fd_ofiles;
  596.     for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
  597.         if (*fpp)
  598.             (void) closef(*fpp, p);
  599.     if (fdp->fd_nfiles > NDFILE)
  600.         FREE(fdp->fd_ofiles, M_FILEDESC);
  601.     vrele(fdp->fd_cdir);
  602.     if (fdp->fd_rdir)
  603.         vrele(fdp->fd_rdir);
  604.     FREE(fdp, M_FILEDESC);
  605. }
  606.  
  607. /*
  608.  * Internal form of close.
  609.  * Decrement reference count on file structure.
  610.  */
  611. closef(fp, p)
  612.     register struct file *fp;
  613.     register struct proc *p;
  614. {
  615.     struct vnode *vp;
  616.     struct flock lf;
  617.     int error;
  618.  
  619.     if (fp == NULL)
  620.         return (0);
  621.     /*
  622.      * POSIX record locking dictates that any close releases ALL
  623.      * locks owned by this process.  This is handled by setting
  624.      * a flag in the unlock to free ONLY locks obeying POSIX
  625.      * semantics, and not to free BSD-style file locks.
  626.      */
  627.     if ((p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) {
  628.         lf.l_whence = SEEK_SET;
  629.         lf.l_start = 0;
  630.         lf.l_len = 0;
  631.         lf.l_type = F_UNLCK;
  632.         vp = (struct vnode *)fp->f_data;
  633.         (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
  634.     }
  635.     if (--fp->f_count > 0)
  636.         return (0);
  637.     if (fp->f_count < 0)
  638.         panic("closef: count < 0");
  639.     if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
  640.         lf.l_whence = SEEK_SET;
  641.         lf.l_start = 0;
  642.         lf.l_len = 0;
  643.         lf.l_type = F_UNLCK;
  644.         vp = (struct vnode *)fp->f_data;
  645.         (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
  646.     }
  647.     error = (*fp->f_ops->fo_close)(fp, p);
  648.     ffree(fp);
  649.     return (error);
  650. }
  651.  
  652. /*
  653.  * Apply an advisory lock on a file descriptor.
  654.  *
  655.  * Just attempt to get a record lock of the requested type on
  656.  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
  657.  */
  658.  
  659. /* ARGSUSED */
  660. flock(p, uap, retval)
  661.     struct proc *p;
  662.     register struct args {
  663.         int    fd;
  664.         int    how;
  665.     } *uap;
  666.     int *retval;
  667. {
  668.     register struct filedesc *fdp = p->p_fd;
  669.     register struct file *fp;
  670.     struct vnode *vp;
  671.     struct flock lf;
  672.     int error;
  673.  
  674.     if ((unsigned)uap->fd >= fdp->fd_nfiles ||
  675.         (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  676.         return (EBADF);
  677.     if (fp->f_type != DTYPE_VNODE)
  678.         return (EOPNOTSUPP);
  679.     vp = (struct vnode *)fp->f_data;
  680.     lf.l_whence = SEEK_SET;
  681.     lf.l_start = 0;
  682.     lf.l_len = 0;
  683.     if (uap->how & LOCK_UN) {
  684.         lf.l_type = F_UNLCK;
  685.         fp->f_flag &= ~FHASLOCK;
  686.         return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
  687.     }
  688.     if (uap->how & LOCK_EX)
  689.         lf.l_type = F_WRLCK;
  690.     else if (uap->how & LOCK_SH)
  691.         lf.l_type = F_RDLCK;
  692.     else
  693.         return (EBADF);
  694.     fp->f_flag |= FHASLOCK;
  695.     if (uap->how & LOCK_NB)
  696.         return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
  697.     return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
  698. }
  699.  
  700. /*
  701.  * File Descriptor pseudo-device driver (/dev/fd/).
  702.  *
  703.  * Opening minor device N dup()s the file (if any) connected to file
  704.  * descriptor N belonging to the calling process.  Note that this driver
  705.  * consists of only the ``open()'' routine, because all subsequent
  706.  * references to this file will be direct to the other driver.
  707.  */
  708. /* ARGSUSED */
  709. fdopen(dev, mode, type)
  710.     dev_t dev;
  711.     int mode, type;
  712. {
  713.  
  714.     /*
  715.      * XXX Kludge: set curproc->p_dupfd to contain the value of the
  716.      * the file descriptor being sought for duplication. The error 
  717.      * return ensures that the vnode for this device will be released
  718.      * by vn_open. Open will detect this special error and take the
  719.      * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
  720.      * will simply report the error.
  721.      */
  722.     curproc->p_dupfd = minor(dev);        /* XXX */
  723.     return (ENODEV);
  724. }
  725.  
  726. /*
  727.  * Duplicate the specified descriptor to a free descriptor.
  728.  */
  729. dupfdopen(fdp, indx, dfd, mode)
  730.     register struct filedesc *fdp;
  731.     register int indx, dfd;
  732.     int mode;
  733. {
  734.     register struct file *wfp;
  735.     struct file *fp;
  736.     
  737.     /*
  738.      * If the to-be-dup'd fd number is greater than the allowed number
  739.      * of file descriptors, or the fd to be dup'd has already been
  740.      * closed, reject.  Note, check for new == old is necessary as
  741.      * falloc could allocate an already closed to-be-dup'd descriptor
  742.      * as the new descriptor.
  743.      */
  744.     fp = fdp->fd_ofiles[indx];
  745.     if ((u_int)dfd >= fdp->fd_nfiles ||
  746.         (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
  747.         return (EBADF);
  748.  
  749.     /*
  750.      * Check that the mode the file is being opened for is a subset 
  751.      * of the mode of the existing descriptor.
  752.      */
  753.     if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
  754.         return (EACCES);
  755.     fdp->fd_ofiles[indx] = wfp;
  756.     fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
  757.     wfp->f_count++;
  758.     if (indx > fdp->fd_lastfile)
  759.         fdp->fd_lastfile = indx;
  760.     return (0);
  761. }
  762.