|
|
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: 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.