home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / fifo_vnops.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-15  |  9.1 KB  |  421 lines

  1. /*
  2.  * Copyright (c) 1990 The 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.  *    @(#)fifo_vnops.c    7.7 (Berkeley) 4/15/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "time.h"
  38. #include "namei.h"
  39. #include "vnode.h"
  40. #include "socket.h"
  41. #include "socketvar.h"
  42. #include "stat.h"
  43. #include "systm.h"
  44. #include "ioctl.h"
  45. #include "file.h"
  46. #include "fifo.h"
  47. #include "errno.h"
  48. #include "malloc.h"
  49.  
  50. /*
  51.  * This structure is associated with the FIFO vnode and stores
  52.  * the state associated with the FIFO.
  53.  */
  54. struct fifoinfo {
  55.     struct socket    *fi_readsock;
  56.     struct socket    *fi_writesock;
  57.     long        fi_readers;
  58.     long        fi_writers;
  59. };
  60.  
  61. struct vnodeops fifo_vnodeops = {
  62.     fifo_lookup,        /* lookup */
  63.     fifo_create,        /* create */
  64.     fifo_mknod,        /* mknod */
  65.     fifo_open,        /* open */
  66.     fifo_close,        /* close */
  67.     fifo_access,        /* access */
  68.     fifo_getattr,        /* getattr */
  69.     fifo_setattr,        /* setattr */
  70.     fifo_read,        /* read */
  71.     fifo_write,        /* write */
  72.     fifo_ioctl,        /* ioctl */
  73.     fifo_select,        /* select */
  74.     fifo_mmap,        /* mmap */
  75.     fifo_fsync,        /* fsync */
  76.     fifo_seek,        /* seek */
  77.     fifo_remove,        /* remove */
  78.     fifo_link,        /* link */
  79.     fifo_rename,        /* rename */
  80.     fifo_mkdir,        /* mkdir */
  81.     fifo_rmdir,        /* rmdir */
  82.     fifo_symlink,        /* symlink */
  83.     fifo_readdir,        /* readdir */
  84.     fifo_readlink,        /* readlink */
  85.     fifo_abortop,        /* abortop */
  86.     fifo_inactive,        /* inactive */
  87.     fifo_reclaim,        /* reclaim */
  88.     fifo_lock,        /* lock */
  89.     fifo_unlock,        /* unlock */
  90.     fifo_bmap,        /* bmap */
  91.     fifo_strategy,        /* strategy */
  92.     fifo_print,        /* print */
  93.     fifo_islocked,        /* islocked */
  94.     fifo_advlock,        /* advlock */
  95. };
  96.  
  97. /*
  98.  * Trivial lookup routine that always fails.
  99.  */
  100. /* ARGSUSED */
  101. fifo_lookup(vp, ndp, p)
  102.     struct vnode *vp;
  103.     struct nameidata *ndp;
  104.     struct proc *p;
  105. {
  106.  
  107.     ndp->ni_dvp = vp;
  108.     ndp->ni_vp = NULL;
  109.     return (ENOTDIR);
  110. }
  111.  
  112. /*
  113.  * Open called to set up a new instance of a fifo or
  114.  * to find an active instance of a fifo.
  115.  */
  116. /* ARGSUSED */
  117. fifo_open(vp, mode, cred, p)
  118.     register struct vnode *vp;
  119.     int mode;
  120.     struct ucred *cred;
  121.     struct proc *p;
  122. {
  123.     register struct fifoinfo *fip;
  124.     struct socket *rso, *wso;
  125.     int error;
  126.     static char openstr[] = "fifo";
  127.  
  128.     if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
  129.         return (EINVAL);
  130.     if ((fip = vp->v_fifoinfo) == NULL) {
  131.         MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
  132.         vp->v_fifoinfo = fip;
  133.         if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
  134.             free(fip, M_VNODE);
  135.             vp->v_fifoinfo = NULL;
  136.             return (error);
  137.         }
  138.         fip->fi_readsock = rso;
  139.         if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
  140.             (void)soclose(rso);
  141.             free(fip, M_VNODE);
  142.             vp->v_fifoinfo = NULL;
  143.             return (error);
  144.         }
  145.         fip->fi_writesock = wso;
  146.         if (error = unp_connect2(wso, rso)) {
  147.             (void)soclose(wso);
  148.             (void)soclose(rso);
  149.             free(fip, M_VNODE);
  150.             vp->v_fifoinfo = NULL;
  151.             return (error);
  152.         }
  153.         wso->so_state |= SS_CANTRCVMORE;
  154.         rso->so_state |= SS_CANTSENDMORE;
  155.     }
  156.     error = 0;
  157.     if (mode & FREAD) {
  158.         fip->fi_readers++;
  159.         if (fip->fi_readers == 1) {
  160.             fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
  161.             if (fip->fi_writers > 0)
  162.                 wakeup((caddr_t)&fip->fi_writers);
  163.         }
  164.         if (mode & O_NONBLOCK)
  165.             return (0);
  166.         while (fip->fi_writers == 0)
  167.             if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
  168.                 openstr, 0))
  169.                 break;
  170.     } else {
  171.         fip->fi_writers++;
  172.         if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
  173.             error = ENXIO;
  174.         } else {
  175.             if (fip->fi_writers == 1) {
  176.                 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
  177.                 if (fip->fi_readers > 0)
  178.                     wakeup((caddr_t)&fip->fi_readers);
  179.             }
  180.             while (fip->fi_readers == 0)
  181.                 if (error = tsleep((caddr_t)&fip->fi_writers,
  182.                     PSOCK, openstr, 0))
  183.                     break;
  184.         }
  185.     }
  186.     if (error)
  187.         fifo_close(vp, mode, cred, p);
  188.     return (error);
  189. }
  190.  
  191. /*
  192.  * Vnode op for read
  193.  */
  194. /* ARGSUSED */
  195. fifo_read(vp, uio, ioflag, cred)
  196.     struct vnode *vp;
  197.     register struct uio *uio;
  198.     int ioflag;
  199.     struct ucred *cred;
  200. {
  201.     register struct socket *rso = vp->v_fifoinfo->fi_readsock;
  202.     int error, startresid;
  203.  
  204. #ifdef DIAGNOSTIC
  205.     if (uio->uio_rw != UIO_READ)
  206.         panic("fifo_read mode");
  207. #endif
  208.     if (uio->uio_resid == 0)
  209.         return (0);
  210.     if (ioflag & IO_NDELAY)
  211.         rso->so_state |= SS_NBIO;
  212.     startresid = uio->uio_resid;
  213.     VOP_UNLOCK(vp);
  214.     error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
  215.         (struct mbuf **)0, (struct mbuf **)0);
  216.     VOP_LOCK(vp);
  217.     /*
  218.      * Clear EOF indication after first such return.
  219.      */
  220.     if (uio->uio_resid == startresid)
  221.         rso->so_state &= ~SS_CANTRCVMORE;
  222.     if (ioflag & IO_NDELAY)
  223.         rso->so_state &= ~SS_NBIO;
  224.     return (error);
  225. }
  226.  
  227. /*
  228.  * Vnode op for write
  229.  */
  230. /* ARGSUSED */
  231. fifo_write(vp, uio, ioflag, cred)
  232.     struct vnode *vp;
  233.     register struct uio *uio;
  234.     int ioflag;
  235.     struct ucred *cred;
  236. {
  237.     struct socket *wso = vp->v_fifoinfo->fi_writesock;
  238.     int error;
  239.  
  240. #ifdef DIAGNOSTIC
  241.     if (uio->uio_rw != UIO_WRITE)
  242.         panic("fifo_write mode");
  243. #endif
  244.     if (ioflag & IO_NDELAY)
  245.         wso->so_state |= SS_NBIO;
  246.     VOP_UNLOCK(vp);
  247.     error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
  248.     VOP_LOCK(vp);
  249.     if (ioflag & IO_NDELAY)
  250.         wso->so_state &= ~SS_NBIO;
  251.     return (error);
  252. }
  253.  
  254. /*
  255.  * Device ioctl operation.
  256.  */
  257. /* ARGSUSED */
  258. fifo_ioctl(vp, com, data, fflag, cred, p)
  259.     struct vnode *vp;
  260.     int com;
  261.     caddr_t data;
  262.     int fflag;
  263.     struct ucred *cred;
  264.     struct proc *p;
  265. {
  266.     struct file filetmp;
  267.     int error;
  268.  
  269.     if (com == FIONBIO)
  270.         return (0);
  271.     if (fflag & FREAD)
  272.         filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
  273.     else
  274.         filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
  275.     return (soo_ioctl(&filetmp, com, data, p));
  276. }
  277.  
  278. /* ARGSUSED */
  279. fifo_select(vp, which, fflag, cred, p)
  280.     struct vnode *vp;
  281.     int which, fflag;
  282.     struct ucred *cred;
  283.     struct proc *p;
  284. {
  285.     struct file filetmp;
  286.     int error;
  287.  
  288.     if (fflag & FREAD)
  289.         filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
  290.     else
  291.         filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
  292.     return (soo_select(&filetmp, which, p));
  293. }
  294.  
  295. /*
  296.  * This is a noop, simply returning what one has been given.
  297.  */
  298. fifo_bmap(vp, bn, vpp, bnp)
  299.     struct vnode *vp;
  300.     daddr_t bn;
  301.     struct vnode **vpp;
  302.     daddr_t *bnp;
  303. {
  304.  
  305.     if (vpp != NULL)
  306.         *vpp = vp;
  307.     if (bnp != NULL)
  308.         *bnp = bn;
  309.     return (0);
  310. }
  311.  
  312. /*
  313.  * At the moment we do not do any locking.
  314.  */
  315. /* ARGSUSED */
  316. fifo_lock(vp)
  317.     struct vnode *vp;
  318. {
  319.  
  320.     return (0);
  321. }
  322.  
  323. /* ARGSUSED */
  324. fifo_unlock(vp)
  325.     struct vnode *vp;
  326. {
  327.  
  328.     return (0);
  329. }
  330.  
  331. /*
  332.  * Device close routine
  333.  */
  334. /* ARGSUSED */
  335. fifo_close(vp, fflag, cred, p)
  336.     register struct vnode *vp;
  337.     int fflag;
  338.     struct ucred *cred;
  339.     struct proc *p;
  340. {
  341.     register struct fifoinfo *fip = vp->v_fifoinfo;
  342.     int error1, error2;
  343.  
  344.     if (fflag & FWRITE) {
  345.         fip->fi_writers--;
  346.         if (fip->fi_writers == 0)
  347.             socantrcvmore(fip->fi_readsock);
  348.     } else {
  349.         fip->fi_readers--;
  350.         if (fip->fi_readers == 0)
  351.             socantsendmore(fip->fi_writesock);
  352.     }
  353.     if (vp->v_usecount > 1)
  354.         return (0);
  355.     error1 = soclose(fip->fi_readsock);
  356.     error2 = soclose(fip->fi_writesock);
  357.     FREE(fip, M_VNODE);
  358.     vp->v_fifoinfo = NULL;
  359.     if (error1)
  360.         return (error1);
  361.     return (error2);
  362. }
  363.  
  364. /*
  365.  * Print out the contents of a fifo vnode.
  366.  */
  367. fifo_print(vp)
  368.     struct vnode *vp;
  369. {
  370.  
  371.     printf("tag VT_NON");
  372.     fifo_printinfo(vp);
  373.     printf("\n");
  374. }
  375.  
  376. /*
  377.  * Print out internal contents of a fifo vnode.
  378.  */
  379. fifo_printinfo(vp)
  380.     struct vnode *vp;
  381. {
  382.     register struct fifoinfo *fip = vp->v_fifoinfo;
  383.  
  384.     printf(", fifo with %d readers and %d writers",
  385.         fip->fi_readers, fip->fi_writers);
  386. }
  387.  
  388. /*
  389.  * Fifo failed operation
  390.  */
  391. fifo_ebadf()
  392. {
  393.  
  394.     return (EBADF);
  395. }
  396.  
  397. /*
  398.  * Fifo advisory byte-level locks.
  399.  */
  400. /* ARGSUSED */
  401. fifo_advlock(vp, id, op, fl, flags)
  402.     struct vnode *vp;
  403.     caddr_t id;
  404.     int op;
  405.     struct flock *fl;
  406.     int flags;
  407. {
  408.  
  409.     return (EOPNOTSUPP);
  410. }
  411.  
  412. /*
  413.  * Fifo bad operation
  414.  */
  415. fifo_badop()
  416. {
  417.  
  418.     panic("fifo_badop called");
  419.     /* NOTREACHED */
  420. }
  421.