|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)fifo_vnops.c 7.4 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "time.h" ! 25: #include "namei.h" ! 26: #include "vnode.h" ! 27: #include "socket.h" ! 28: #include "socketvar.h" ! 29: #include "stat.h" ! 30: #include "ioctl.h" ! 31: #include "file.h" ! 32: #include "errno.h" ! 33: #include "malloc.h" ! 34: ! 35: /* ! 36: * This structure is associated with the FIFO vnode and stores ! 37: * the state associated with the FIFO. ! 38: */ ! 39: struct fifoinfo { ! 40: struct socket *fi_readsock; ! 41: struct socket *fi_writesock; ! 42: long fi_readers; ! 43: long fi_writers; ! 44: }; ! 45: ! 46: int fifo_lookup(), ! 47: fifo_open(), ! 48: fifo_read(), ! 49: fifo_write(), ! 50: fifo_strategy(), ! 51: fifo_bmap(), ! 52: fifo_ioctl(), ! 53: fifo_select(), ! 54: fifo_lock(), ! 55: fifo_unlock(), ! 56: fifo_close(), ! 57: fifo_print(), ! 58: fifo_ebadf(), ! 59: fifo_badop(), ! 60: fifo_nullop(); ! 61: ! 62: struct vnodeops fifo_vnodeops = { ! 63: fifo_lookup, /* lookup */ ! 64: fifo_badop, /* create */ ! 65: fifo_badop, /* mknod */ ! 66: fifo_open, /* open */ ! 67: fifo_close, /* close */ ! 68: fifo_ebadf, /* access */ ! 69: fifo_ebadf, /* getattr */ ! 70: fifo_ebadf, /* setattr */ ! 71: fifo_read, /* read */ ! 72: fifo_write, /* write */ ! 73: fifo_ioctl, /* ioctl */ ! 74: fifo_select, /* select */ ! 75: fifo_badop, /* mmap */ ! 76: fifo_nullop, /* fsync */ ! 77: fifo_badop, /* seek */ ! 78: fifo_badop, /* remove */ ! 79: fifo_badop, /* link */ ! 80: fifo_badop, /* rename */ ! 81: fifo_badop, /* mkdir */ ! 82: fifo_badop, /* rmdir */ ! 83: fifo_badop, /* symlink */ ! 84: fifo_badop, /* readdir */ ! 85: fifo_badop, /* readlink */ ! 86: fifo_badop, /* abortop */ ! 87: fifo_nullop, /* inactive */ ! 88: fifo_nullop, /* reclaim */ ! 89: fifo_lock, /* lock */ ! 90: fifo_unlock, /* unlock */ ! 91: fifo_bmap, /* bmap */ ! 92: fifo_badop, /* strategy */ ! 93: fifo_print, /* print */ ! 94: fifo_nullop, /* islocked */ ! 95: }; ! 96: ! 97: /* ! 98: * Trivial lookup routine that always fails. ! 99: */ ! 100: fifo_lookup(vp, ndp) ! 101: struct vnode *vp; ! 102: struct nameidata *ndp; ! 103: { ! 104: ! 105: ndp->ni_dvp = vp; ! 106: ndp->ni_vp = NULL; ! 107: return (ENOTDIR); ! 108: } ! 109: ! 110: /* ! 111: * Open called to set up a new instance of a fifo or ! 112: * to find an active instance of a fifo. ! 113: */ ! 114: /* ARGSUSED */ ! 115: fifo_open(vp, mode, cred) ! 116: register struct vnode *vp; ! 117: int mode; ! 118: struct ucred *cred; ! 119: { ! 120: register struct fifoinfo *fip; ! 121: struct socket *rso, *wso; ! 122: int error; ! 123: static char openstr[] = "fifo"; ! 124: ! 125: if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) ! 126: return (EINVAL); ! 127: if ((fip = vp->v_fifoinfo) == NULL) { ! 128: MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); ! 129: vp->v_fifoinfo = fip; ! 130: if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { ! 131: free(fip, M_VNODE); ! 132: vp->v_fifoinfo = NULL; ! 133: return (error); ! 134: } ! 135: fip->fi_readsock = rso; ! 136: if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { ! 137: (void)soclose(rso); ! 138: free(fip, M_VNODE); ! 139: vp->v_fifoinfo = NULL; ! 140: return (error); ! 141: } ! 142: fip->fi_writesock = wso; ! 143: if (error = unp_connect2(wso, rso)) { ! 144: (void)soclose(wso); ! 145: (void)soclose(rso); ! 146: free(fip, M_VNODE); ! 147: vp->v_fifoinfo = NULL; ! 148: return (error); ! 149: } ! 150: wso->so_state |= SS_CANTRCVMORE; ! 151: rso->so_state |= SS_CANTSENDMORE; ! 152: } ! 153: error = 0; ! 154: if (mode & FREAD) { ! 155: fip->fi_readers++; ! 156: if (fip->fi_readers == 1) { ! 157: fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; ! 158: if (fip->fi_writers > 0) ! 159: wakeup((caddr_t)&fip->fi_writers); ! 160: } ! 161: if (mode & O_NONBLOCK) ! 162: return (0); ! 163: while (fip->fi_writers == 0) ! 164: if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK, ! 165: openstr, 0)) ! 166: break; ! 167: } else { ! 168: fip->fi_writers++; ! 169: if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { ! 170: error = ENXIO; ! 171: } else { ! 172: if (fip->fi_writers == 1) { ! 173: fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; ! 174: if (fip->fi_readers > 0) ! 175: wakeup((caddr_t)&fip->fi_readers); ! 176: } ! 177: while (fip->fi_readers == 0) ! 178: if (error = tsleep((caddr_t)&fip->fi_writers, ! 179: PSOCK, openstr, 0)) ! 180: break; ! 181: } ! 182: } ! 183: if (error) ! 184: fifo_close(vp, mode, cred); ! 185: return (error); ! 186: } ! 187: ! 188: /* ! 189: * Vnode op for read ! 190: */ ! 191: /* ARGSUSED */ ! 192: fifo_read(vp, uio, ioflag, cred) ! 193: struct vnode *vp; ! 194: register struct uio *uio; ! 195: int ioflag; ! 196: struct ucred *cred; ! 197: { ! 198: register struct socket *rso = vp->v_fifoinfo->fi_readsock; ! 199: int error, startresid; ! 200: ! 201: if (uio->uio_rw != UIO_READ) ! 202: panic("fifo_read mode"); ! 203: if (uio->uio_resid == 0) ! 204: return (0); ! 205: if (ioflag & IO_NDELAY) ! 206: rso->so_state |= SS_NBIO; ! 207: startresid = uio->uio_resid; ! 208: VOP_UNLOCK(vp); ! 209: error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, ! 210: (struct mbuf **)0, (struct mbuf **)0); ! 211: VOP_LOCK(vp); ! 212: /* ! 213: * Clear EOF indication after first such return. ! 214: */ ! 215: if (uio->uio_resid == startresid) ! 216: rso->so_state &= ~SS_CANTRCVMORE; ! 217: if (ioflag & IO_NDELAY) ! 218: rso->so_state &= ~SS_NBIO; ! 219: return (error); ! 220: } ! 221: ! 222: /* ! 223: * Vnode op for write ! 224: */ ! 225: /* ARGSUSED */ ! 226: fifo_write(vp, uio, ioflag, cred) ! 227: struct vnode *vp; ! 228: register struct uio *uio; ! 229: int ioflag; ! 230: struct ucred *cred; ! 231: { ! 232: struct socket *wso = vp->v_fifoinfo->fi_writesock; ! 233: int error; ! 234: ! 235: if (uio->uio_rw != UIO_WRITE) ! 236: panic("fifo_write mode"); ! 237: if (ioflag & IO_NDELAY) ! 238: wso->so_state |= SS_NBIO; ! 239: VOP_UNLOCK(vp); ! 240: error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); ! 241: VOP_LOCK(vp); ! 242: if (ioflag & IO_NDELAY) ! 243: wso->so_state &= ~SS_NBIO; ! 244: return (error); ! 245: } ! 246: ! 247: /* ! 248: * Device ioctl operation. ! 249: */ ! 250: /* ARGSUSED */ ! 251: fifo_ioctl(vp, com, data, fflag, cred) ! 252: struct vnode *vp; ! 253: int com; ! 254: caddr_t data; ! 255: int fflag; ! 256: struct ucred *cred; ! 257: { ! 258: struct file filetmp; ! 259: int error; ! 260: ! 261: if (com == FIONBIO) ! 262: return (0); ! 263: if (fflag & FREAD) ! 264: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; ! 265: else ! 266: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; ! 267: return (soo_ioctl(&filetmp, com, data)); ! 268: } ! 269: ! 270: /* ARGSUSED */ ! 271: fifo_select(vp, which, fflag, cred) ! 272: struct vnode *vp; ! 273: int which, fflag; ! 274: struct ucred *cred; ! 275: { ! 276: struct file filetmp; ! 277: int error; ! 278: ! 279: if (fflag & FREAD) ! 280: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; ! 281: else ! 282: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; ! 283: return (soo_select(&filetmp, which)); ! 284: } ! 285: ! 286: /* ! 287: * This is a noop, simply returning what one has been given. ! 288: */ ! 289: fifo_bmap(vp, bn, vpp, bnp) ! 290: struct vnode *vp; ! 291: daddr_t bn; ! 292: struct vnode **vpp; ! 293: daddr_t *bnp; ! 294: { ! 295: ! 296: if (vpp != NULL) ! 297: *vpp = vp; ! 298: if (bnp != NULL) ! 299: *bnp = bn; ! 300: return (0); ! 301: } ! 302: ! 303: /* ! 304: * At the moment we do not do any locking. ! 305: */ ! 306: /* ARGSUSED */ ! 307: fifo_lock(vp) ! 308: struct vnode *vp; ! 309: { ! 310: ! 311: return (0); ! 312: } ! 313: ! 314: /* ARGSUSED */ ! 315: fifo_unlock(vp) ! 316: struct vnode *vp; ! 317: { ! 318: ! 319: return (0); ! 320: } ! 321: ! 322: /* ! 323: * Device close routine ! 324: */ ! 325: /* ARGSUSED */ ! 326: fifo_close(vp, fflag, cred) ! 327: register struct vnode *vp; ! 328: int fflag; ! 329: struct ucred *cred; ! 330: { ! 331: register struct fifoinfo *fip = vp->v_fifoinfo; ! 332: int error1, error2; ! 333: ! 334: if (fflag & FWRITE) { ! 335: fip->fi_writers--; ! 336: if (fip->fi_writers == 0) ! 337: socantrcvmore(fip->fi_readsock); ! 338: } else { ! 339: fip->fi_readers--; ! 340: if (fip->fi_readers == 0) ! 341: socantsendmore(fip->fi_writesock); ! 342: } ! 343: if (vp->v_usecount > 1) ! 344: return (0); ! 345: error1 = soclose(fip->fi_readsock); ! 346: error2 = soclose(fip->fi_writesock); ! 347: FREE(fip, M_VNODE); ! 348: vp->v_fifoinfo = NULL; ! 349: if (error1) ! 350: return (error1); ! 351: return (error2); ! 352: } ! 353: ! 354: /* ! 355: * Print out the contents of a fifo vnode. ! 356: */ ! 357: fifo_print(vp) ! 358: struct vnode *vp; ! 359: { ! 360: ! 361: printf("tag VT_NON"); ! 362: fifo_printinfo(vp); ! 363: printf("\n"); ! 364: } ! 365: ! 366: /* ! 367: * Print out internal contents of a fifo vnode. ! 368: */ ! 369: fifo_printinfo(vp) ! 370: struct vnode *vp; ! 371: { ! 372: register struct fifoinfo *fip = vp->v_fifoinfo; ! 373: ! 374: printf(", fifo with %d readers and %d writers", ! 375: fip->fi_readers, fip->fi_writers); ! 376: } ! 377: ! 378: /* ! 379: * Fifo failed operation ! 380: */ ! 381: fifo_ebadf() ! 382: { ! 383: ! 384: return (EBADF); ! 385: } ! 386: ! 387: /* ! 388: * Fifo bad operation ! 389: */ ! 390: fifo_badop() ! 391: { ! 392: ! 393: panic("fifo_badop called"); ! 394: /* NOTREACHED */ ! 395: } ! 396: ! 397: /* ! 398: * Fifo null operation ! 399: */ ! 400: fifo_nullop() ! 401: { ! 402: ! 403: return (0); ! 404: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.