|
|
1.1 ! root 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: fip->fi_readers=0; ! 134: fip->fi_writers=0; ! 135: if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { ! 136: free(fip, M_VNODE); ! 137: vp->v_fifoinfo = NULL; ! 138: return (error); ! 139: } ! 140: fip->fi_readsock = rso; ! 141: if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { ! 142: (void)soclose(rso); ! 143: free(fip, M_VNODE); ! 144: vp->v_fifoinfo = NULL; ! 145: return (error); ! 146: } ! 147: fip->fi_writesock = wso; ! 148: if (error = unp_connect2(wso, rso)) { ! 149: (void)soclose(wso); ! 150: (void)soclose(rso); ! 151: free(fip, M_VNODE); ! 152: vp->v_fifoinfo = NULL; ! 153: return (error); ! 154: } ! 155: wso->so_state |= SS_CANTRCVMORE; ! 156: rso->so_state |= SS_CANTSENDMORE; ! 157: } ! 158: error = 0; ! 159: if (mode & FREAD) { ! 160: fip->fi_readers++; ! 161: if (fip->fi_readers == 1) { ! 162: fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; ! 163: if (fip->fi_writers > 0) ! 164: wakeup((caddr_t)&fip->fi_writers); ! 165: } ! 166: if (mode & O_NONBLOCK) ! 167: return (0); ! 168: while (fip->fi_writers == 0) { ! 169: VOP_UNLOCK(vp); ! 170: error = tsleep((caddr_t)&fip->fi_readers, PSOCK, ! 171: openstr, 0); ! 172: VOP_LOCK(vp); ! 173: if(error) ! 174: break; ! 175: } ! 176: } else { ! 177: fip->fi_writers++; ! 178: if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { ! 179: error = ENXIO; ! 180: } else { ! 181: if (fip->fi_writers == 1) { ! 182: fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; ! 183: if (fip->fi_readers > 0) ! 184: wakeup((caddr_t)&fip->fi_readers); ! 185: } ! 186: while (fip->fi_readers == 0) { ! 187: VOP_UNLOCK(vp); ! 188: error = tsleep((caddr_t)&fip->fi_writers, ! 189: PSOCK, openstr, 0); ! 190: VOP_LOCK(vp); ! 191: if(error) ! 192: break; ! 193: } ! 194: } ! 195: } ! 196: if (error) ! 197: fifo_close(vp, mode, cred, p); ! 198: return (error); ! 199: } ! 200: ! 201: /* ! 202: * Vnode op for read ! 203: */ ! 204: /* ARGSUSED */ ! 205: fifo_read(vp, uio, ioflag, cred) ! 206: struct vnode *vp; ! 207: register struct uio *uio; ! 208: int ioflag; ! 209: struct ucred *cred; ! 210: { ! 211: register struct socket *rso = vp->v_fifoinfo->fi_readsock; ! 212: int error, startresid; ! 213: ! 214: #ifdef DIAGNOSTIC ! 215: if (uio->uio_rw != UIO_READ) ! 216: panic("fifo_read mode"); ! 217: #endif ! 218: if (uio->uio_resid == 0) ! 219: return (0); ! 220: if (ioflag & IO_NDELAY) ! 221: rso->so_state |= SS_NBIO; ! 222: startresid = uio->uio_resid; ! 223: VOP_UNLOCK(vp); ! 224: error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, ! 225: (struct mbuf **)0, (struct mbuf **)0); ! 226: VOP_LOCK(vp); ! 227: /* ! 228: * Clear EOF indication after first such return. ! 229: */ ! 230: if (uio->uio_resid == startresid) ! 231: rso->so_state &= ~SS_CANTRCVMORE; ! 232: if (ioflag & IO_NDELAY) ! 233: rso->so_state &= ~SS_NBIO; ! 234: return (error); ! 235: } ! 236: ! 237: /* ! 238: * Vnode op for write ! 239: */ ! 240: /* ARGSUSED */ ! 241: fifo_write(vp, uio, ioflag, cred) ! 242: struct vnode *vp; ! 243: register struct uio *uio; ! 244: int ioflag; ! 245: struct ucred *cred; ! 246: { ! 247: struct socket *wso = vp->v_fifoinfo->fi_writesock; ! 248: int error; ! 249: ! 250: #ifdef DIAGNOSTIC ! 251: if (uio->uio_rw != UIO_WRITE) ! 252: panic("fifo_write mode"); ! 253: #endif ! 254: if (ioflag & IO_NDELAY) ! 255: wso->so_state |= SS_NBIO; ! 256: VOP_UNLOCK(vp); ! 257: error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); ! 258: VOP_LOCK(vp); ! 259: if (ioflag & IO_NDELAY) ! 260: wso->so_state &= ~SS_NBIO; ! 261: return (error); ! 262: } ! 263: ! 264: /* ! 265: * Device ioctl operation. ! 266: */ ! 267: /* ARGSUSED */ ! 268: fifo_ioctl(vp, com, data, fflag, cred, p) ! 269: struct vnode *vp; ! 270: int com; ! 271: caddr_t data; ! 272: int fflag; ! 273: struct ucred *cred; ! 274: struct proc *p; ! 275: { ! 276: struct file filetmp; ! 277: int error; ! 278: ! 279: if (com == FIONBIO) ! 280: return (0); ! 281: if (fflag & FREAD) ! 282: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; ! 283: else ! 284: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; ! 285: return (soo_ioctl(&filetmp, com, data, p)); ! 286: } ! 287: ! 288: /* ARGSUSED */ ! 289: fifo_select(vp, which, fflag, cred, p) ! 290: struct vnode *vp; ! 291: int which, fflag; ! 292: struct ucred *cred; ! 293: struct proc *p; ! 294: { ! 295: struct file filetmp; ! 296: int error; ! 297: ! 298: if (fflag & FREAD) ! 299: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; ! 300: else ! 301: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; ! 302: return (soo_select(&filetmp, which, p)); ! 303: } ! 304: ! 305: /* ! 306: * This is a noop, simply returning what one has been given. ! 307: */ ! 308: fifo_bmap(vp, bn, vpp, bnp) ! 309: struct vnode *vp; ! 310: daddr_t bn; ! 311: struct vnode **vpp; ! 312: daddr_t *bnp; ! 313: { ! 314: ! 315: if (vpp != NULL) ! 316: *vpp = vp; ! 317: if (bnp != NULL) ! 318: *bnp = bn; ! 319: return (0); ! 320: } ! 321: ! 322: /* ! 323: * At the moment we do not do any locking. ! 324: */ ! 325: /* ARGSUSED */ ! 326: fifo_lock(vp) ! 327: struct vnode *vp; ! 328: { ! 329: ! 330: return (0); ! 331: } ! 332: ! 333: /* ARGSUSED */ ! 334: fifo_unlock(vp) ! 335: struct vnode *vp; ! 336: { ! 337: ! 338: return (0); ! 339: } ! 340: ! 341: /* ! 342: * Device close routine ! 343: */ ! 344: /* ARGSUSED */ ! 345: fifo_close(vp, fflag, cred, p) ! 346: register struct vnode *vp; ! 347: int fflag; ! 348: struct ucred *cred; ! 349: struct proc *p; ! 350: { ! 351: register struct fifoinfo *fip = vp->v_fifoinfo; ! 352: int error1, error2; ! 353: ! 354: if (fflag & FWRITE) { ! 355: fip->fi_writers--; ! 356: if (fip->fi_writers == 0) ! 357: socantrcvmore(fip->fi_readsock); ! 358: } else { ! 359: fip->fi_readers--; ! 360: if (fip->fi_readers == 0) ! 361: socantsendmore(fip->fi_writesock); ! 362: } ! 363: if (vp->v_usecount > 1) ! 364: return (0); ! 365: error1 = soclose(fip->fi_readsock); ! 366: error2 = soclose(fip->fi_writesock); ! 367: FREE(fip, M_VNODE); ! 368: vp->v_fifoinfo = NULL; ! 369: if (error1) ! 370: return (error1); ! 371: return (error2); ! 372: } ! 373: ! 374: /* ! 375: * Print out the contents of a fifo vnode. ! 376: */ ! 377: fifo_print(vp) ! 378: struct vnode *vp; ! 379: { ! 380: ! 381: printf("tag VT_NON"); ! 382: fifo_printinfo(vp); ! 383: printf("\n"); ! 384: } ! 385: ! 386: /* ! 387: * Print out internal contents of a fifo vnode. ! 388: */ ! 389: fifo_printinfo(vp) ! 390: struct vnode *vp; ! 391: { ! 392: register struct fifoinfo *fip = vp->v_fifoinfo; ! 393: ! 394: printf(", fifo with %d readers and %d writers", ! 395: fip->fi_readers, fip->fi_writers); ! 396: } ! 397: ! 398: /* ! 399: * Fifo failed operation ! 400: */ ! 401: fifo_ebadf() ! 402: { ! 403: ! 404: return (EBADF); ! 405: } ! 406: ! 407: /* ! 408: * Fifo advisory byte-level locks. ! 409: */ ! 410: /* ARGSUSED */ ! 411: fifo_advlock(vp, id, op, fl, flags) ! 412: struct vnode *vp; ! 413: caddr_t id; ! 414: int op; ! 415: struct flock *fl; ! 416: int flags; ! 417: { ! 418: ! 419: return (EOPNOTSUPP); ! 420: } ! 421: ! 422: /* ! 423: * Fifo bad operation ! 424: */ ! 425: fifo_badop() ! 426: { ! 427: ! 428: panic("fifo_badop called"); ! 429: /* NOTREACHED */ ! 430: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.