home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fifo_vnops.c 7.7 (Berkeley) 4/15/91
- */
-
- #include "param.h"
- #include "time.h"
- #include "namei.h"
- #include "vnode.h"
- #include "socket.h"
- #include "socketvar.h"
- #include "stat.h"
- #include "systm.h"
- #include "ioctl.h"
- #include "file.h"
- #include "fifo.h"
- #include "errno.h"
- #include "malloc.h"
-
- /*
- * This structure is associated with the FIFO vnode and stores
- * the state associated with the FIFO.
- */
- struct fifoinfo {
- struct socket *fi_readsock;
- struct socket *fi_writesock;
- long fi_readers;
- long fi_writers;
- };
-
- struct vnodeops fifo_vnodeops = {
- fifo_lookup, /* lookup */
- fifo_create, /* create */
- fifo_mknod, /* mknod */
- fifo_open, /* open */
- fifo_close, /* close */
- fifo_access, /* access */
- fifo_getattr, /* getattr */
- fifo_setattr, /* setattr */
- fifo_read, /* read */
- fifo_write, /* write */
- fifo_ioctl, /* ioctl */
- fifo_select, /* select */
- fifo_mmap, /* mmap */
- fifo_fsync, /* fsync */
- fifo_seek, /* seek */
- fifo_remove, /* remove */
- fifo_link, /* link */
- fifo_rename, /* rename */
- fifo_mkdir, /* mkdir */
- fifo_rmdir, /* rmdir */
- fifo_symlink, /* symlink */
- fifo_readdir, /* readdir */
- fifo_readlink, /* readlink */
- fifo_abortop, /* abortop */
- fifo_inactive, /* inactive */
- fifo_reclaim, /* reclaim */
- fifo_lock, /* lock */
- fifo_unlock, /* unlock */
- fifo_bmap, /* bmap */
- fifo_strategy, /* strategy */
- fifo_print, /* print */
- fifo_islocked, /* islocked */
- fifo_advlock, /* advlock */
- };
-
- /*
- * Trivial lookup routine that always fails.
- */
- /* ARGSUSED */
- fifo_lookup(vp, ndp, p)
- struct vnode *vp;
- struct nameidata *ndp;
- struct proc *p;
- {
-
- ndp->ni_dvp = vp;
- ndp->ni_vp = NULL;
- return (ENOTDIR);
- }
-
- /*
- * Open called to set up a new instance of a fifo or
- * to find an active instance of a fifo.
- */
- /* ARGSUSED */
- fifo_open(vp, mode, cred, p)
- register struct vnode *vp;
- int mode;
- struct ucred *cred;
- struct proc *p;
- {
- register struct fifoinfo *fip;
- struct socket *rso, *wso;
- int error;
- static char openstr[] = "fifo";
-
- if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
- return (EINVAL);
- if ((fip = vp->v_fifoinfo) == NULL) {
- MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
- vp->v_fifoinfo = fip;
- if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
- free(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- return (error);
- }
- fip->fi_readsock = rso;
- if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
- (void)soclose(rso);
- free(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- return (error);
- }
- fip->fi_writesock = wso;
- if (error = unp_connect2(wso, rso)) {
- (void)soclose(wso);
- (void)soclose(rso);
- free(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- return (error);
- }
- wso->so_state |= SS_CANTRCVMORE;
- rso->so_state |= SS_CANTSENDMORE;
- }
- error = 0;
- if (mode & FREAD) {
- fip->fi_readers++;
- if (fip->fi_readers == 1) {
- fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
- if (fip->fi_writers > 0)
- wakeup((caddr_t)&fip->fi_writers);
- }
- if (mode & O_NONBLOCK)
- return (0);
- while (fip->fi_writers == 0)
- if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
- openstr, 0))
- break;
- } else {
- fip->fi_writers++;
- if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
- error = ENXIO;
- } else {
- if (fip->fi_writers == 1) {
- fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
- if (fip->fi_readers > 0)
- wakeup((caddr_t)&fip->fi_readers);
- }
- while (fip->fi_readers == 0)
- if (error = tsleep((caddr_t)&fip->fi_writers,
- PSOCK, openstr, 0))
- break;
- }
- }
- if (error)
- fifo_close(vp, mode, cred, p);
- return (error);
- }
-
- /*
- * Vnode op for read
- */
- /* ARGSUSED */
- fifo_read(vp, uio, ioflag, cred)
- struct vnode *vp;
- register struct uio *uio;
- int ioflag;
- struct ucred *cred;
- {
- register struct socket *rso = vp->v_fifoinfo->fi_readsock;
- int error, startresid;
-
- #ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_READ)
- panic("fifo_read mode");
- #endif
- if (uio->uio_resid == 0)
- return (0);
- if (ioflag & IO_NDELAY)
- rso->so_state |= SS_NBIO;
- startresid = uio->uio_resid;
- VOP_UNLOCK(vp);
- error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
- (struct mbuf **)0, (struct mbuf **)0);
- VOP_LOCK(vp);
- /*
- * Clear EOF indication after first such return.
- */
- if (uio->uio_resid == startresid)
- rso->so_state &= ~SS_CANTRCVMORE;
- if (ioflag & IO_NDELAY)
- rso->so_state &= ~SS_NBIO;
- return (error);
- }
-
- /*
- * Vnode op for write
- */
- /* ARGSUSED */
- fifo_write(vp, uio, ioflag, cred)
- struct vnode *vp;
- register struct uio *uio;
- int ioflag;
- struct ucred *cred;
- {
- struct socket *wso = vp->v_fifoinfo->fi_writesock;
- int error;
-
- #ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_WRITE)
- panic("fifo_write mode");
- #endif
- if (ioflag & IO_NDELAY)
- wso->so_state |= SS_NBIO;
- VOP_UNLOCK(vp);
- error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
- VOP_LOCK(vp);
- if (ioflag & IO_NDELAY)
- wso->so_state &= ~SS_NBIO;
- return (error);
- }
-
- /*
- * Device ioctl operation.
- */
- /* ARGSUSED */
- fifo_ioctl(vp, com, data, fflag, cred, p)
- struct vnode *vp;
- int com;
- caddr_t data;
- int fflag;
- struct ucred *cred;
- struct proc *p;
- {
- struct file filetmp;
- int error;
-
- if (com == FIONBIO)
- return (0);
- if (fflag & FREAD)
- filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
- else
- filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
- return (soo_ioctl(&filetmp, com, data, p));
- }
-
- /* ARGSUSED */
- fifo_select(vp, which, fflag, cred, p)
- struct vnode *vp;
- int which, fflag;
- struct ucred *cred;
- struct proc *p;
- {
- struct file filetmp;
- int error;
-
- if (fflag & FREAD)
- filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
- else
- filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
- return (soo_select(&filetmp, which, p));
- }
-
- /*
- * This is a noop, simply returning what one has been given.
- */
- fifo_bmap(vp, bn, vpp, bnp)
- struct vnode *vp;
- daddr_t bn;
- struct vnode **vpp;
- daddr_t *bnp;
- {
-
- if (vpp != NULL)
- *vpp = vp;
- if (bnp != NULL)
- *bnp = bn;
- return (0);
- }
-
- /*
- * At the moment we do not do any locking.
- */
- /* ARGSUSED */
- fifo_lock(vp)
- struct vnode *vp;
- {
-
- return (0);
- }
-
- /* ARGSUSED */
- fifo_unlock(vp)
- struct vnode *vp;
- {
-
- return (0);
- }
-
- /*
- * Device close routine
- */
- /* ARGSUSED */
- fifo_close(vp, fflag, cred, p)
- register struct vnode *vp;
- int fflag;
- struct ucred *cred;
- struct proc *p;
- {
- register struct fifoinfo *fip = vp->v_fifoinfo;
- int error1, error2;
-
- if (fflag & FWRITE) {
- fip->fi_writers--;
- if (fip->fi_writers == 0)
- socantrcvmore(fip->fi_readsock);
- } else {
- fip->fi_readers--;
- if (fip->fi_readers == 0)
- socantsendmore(fip->fi_writesock);
- }
- if (vp->v_usecount > 1)
- return (0);
- error1 = soclose(fip->fi_readsock);
- error2 = soclose(fip->fi_writesock);
- FREE(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- if (error1)
- return (error1);
- return (error2);
- }
-
- /*
- * Print out the contents of a fifo vnode.
- */
- fifo_print(vp)
- struct vnode *vp;
- {
-
- printf("tag VT_NON");
- fifo_printinfo(vp);
- printf("\n");
- }
-
- /*
- * Print out internal contents of a fifo vnode.
- */
- fifo_printinfo(vp)
- struct vnode *vp;
- {
- register struct fifoinfo *fip = vp->v_fifoinfo;
-
- printf(", fifo with %d readers and %d writers",
- fip->fi_readers, fip->fi_writers);
- }
-
- /*
- * Fifo failed operation
- */
- fifo_ebadf()
- {
-
- return (EBADF);
- }
-
- /*
- * Fifo advisory byte-level locks.
- */
- /* ARGSUSED */
- fifo_advlock(vp, id, op, fl, flags)
- struct vnode *vp;
- caddr_t id;
- int op;
- struct flock *fl;
- int flags;
- {
-
- return (EOPNOTSUPP);
- }
-
- /*
- * Fifo bad operation
- */
- fifo_badop()
- {
-
- panic("fifo_badop called");
- /* NOTREACHED */
- }
-