[BACK]Return to fifo_vnops.c CVS log [TXT][DIR] Up to [local] / sys / miscfs / fifofs

Annotation of sys/miscfs/fifofs/fifo_vnops.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: fifo_vnops.c,v 1.24 2007/06/18 08:30:07 jasper Exp $  */
        !             2: /*     $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1990, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. Neither the name of the University nor the names of its contributors
        !            17:  *    may be used to endorse or promote products derived from this software
        !            18:  *    without specific prior written permission.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            30:  * SUCH DAMAGE.
        !            31:  *
        !            32:  *     @(#)fifo_vnops.c        8.4 (Berkeley) 8/10/94
        !            33:  */
        !            34:
        !            35: #include <sys/param.h>
        !            36: #include <sys/proc.h>
        !            37: #include <sys/systm.h>
        !            38: #include <sys/time.h>
        !            39: #include <sys/namei.h>
        !            40: #include <sys/vnode.h>
        !            41: #include <sys/socket.h>
        !            42: #include <sys/socketvar.h>
        !            43: #include <sys/stat.h>
        !            44: #include <sys/ioctl.h>
        !            45: #include <sys/file.h>
        !            46: #include <sys/event.h>
        !            47: #include <sys/errno.h>
        !            48: #include <sys/malloc.h>
        !            49: #include <sys/poll.h>
        !            50: #include <sys/un.h>
        !            51: #include <miscfs/fifofs/fifo.h>
        !            52:
        !            53: /*
        !            54:  * This structure is associated with the FIFO vnode and stores
        !            55:  * the state associated with the FIFO.
        !            56:  */
        !            57: struct fifoinfo {
        !            58:        struct socket   *fi_readsock;
        !            59:        struct socket   *fi_writesock;
        !            60:        long            fi_readers;
        !            61:        long            fi_writers;
        !            62: };
        !            63:
        !            64: int (**fifo_vnodeop_p)(void *);
        !            65: struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
        !            66:        { &vop_default_desc, vn_default_error },
        !            67:        { &vop_lookup_desc, fifo_lookup },              /* lookup */
        !            68:        { &vop_create_desc, fifo_create },              /* create */
        !            69:        { &vop_mknod_desc, fifo_mknod },                /* mknod */
        !            70:        { &vop_open_desc, fifo_open },                  /* open */
        !            71:        { &vop_close_desc, fifo_close },                /* close */
        !            72:        { &vop_access_desc, fifo_access },              /* access */
        !            73:        { &vop_getattr_desc, fifo_getattr },            /* getattr */
        !            74:        { &vop_setattr_desc, fifo_setattr },            /* setattr */
        !            75:        { &vop_read_desc, fifo_read },                  /* read */
        !            76:        { &vop_write_desc, fifo_write },                /* write */
        !            77:        { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
        !            78:        { &vop_poll_desc, fifo_poll },                  /* poll */
        !            79:        { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
        !            80:        { &vop_revoke_desc, fifo_revoke },              /* revoke */
        !            81:        { &vop_fsync_desc, fifo_fsync },                /* fsync */
        !            82:        { &vop_remove_desc, fifo_remove },              /* remove */
        !            83:        { &vop_link_desc, fifo_link },                  /* link */
        !            84:        { &vop_rename_desc, fifo_rename },              /* rename */
        !            85:        { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
        !            86:        { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
        !            87:        { &vop_symlink_desc, fifo_symlink },            /* symlink */
        !            88:        { &vop_readdir_desc, fifo_readdir },            /* readdir */
        !            89:        { &vop_readlink_desc, fifo_readlink },          /* readlink */
        !            90:        { &vop_abortop_desc, fifo_abortop },            /* abortop */
        !            91:        { &vop_inactive_desc, fifo_inactive },          /* inactive */
        !            92:        { &vop_reclaim_desc, fifo_reclaim },            /* reclaim */
        !            93:        { &vop_lock_desc, fifo_lock },                  /* lock */
        !            94:        { &vop_unlock_desc, fifo_unlock },              /* unlock */
        !            95:        { &vop_bmap_desc, fifo_bmap },                  /* bmap */
        !            96:        { &vop_strategy_desc, fifo_strategy },          /* strategy */
        !            97:        { &vop_print_desc, fifo_print },                /* print */
        !            98:        { &vop_islocked_desc, fifo_islocked },          /* islocked */
        !            99:        { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
        !           100:        { &vop_advlock_desc, fifo_advlock },            /* advlock */
        !           101:        { &vop_bwrite_desc, fifo_bwrite },              /* bwrite */
        !           102:        { NULL, NULL }
        !           103: };
        !           104:
        !           105: struct vnodeopv_desc fifo_vnodeop_opv_desc =
        !           106:        { &fifo_vnodeop_p, fifo_vnodeop_entries };
        !           107:
        !           108: int
        !           109: fifo_vnoperate(void *v)
        !           110: {
        !           111:        struct vop_generic_args *ap = v;
        !           112:
        !           113:        return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
        !           114: }
        !           115:
        !           116: void   filt_fifordetach(struct knote *kn);
        !           117: int    filt_fiforead(struct knote *kn, long hint);
        !           118: void   filt_fifowdetach(struct knote *kn);
        !           119: int    filt_fifowrite(struct knote *kn, long hint);
        !           120:
        !           121: struct filterops fiforead_filtops =
        !           122:        { 1, NULL, filt_fifordetach, filt_fiforead };
        !           123: struct filterops fifowrite_filtops =
        !           124:        { 1, NULL, filt_fifowdetach, filt_fifowrite };
        !           125:
        !           126: /*
        !           127:  * Trivial lookup routine that always fails.
        !           128:  */
        !           129: /* ARGSUSED */
        !           130: int
        !           131: fifo_lookup(void *v)
        !           132: {
        !           133:        struct vop_lookup_args *ap = v;
        !           134:
        !           135:        *ap->a_vpp = NULL;
        !           136:        return (ENOTDIR);
        !           137: }
        !           138:
        !           139: /*
        !           140:  * Open called to set up a new instance of a fifo or
        !           141:  * to find an active instance of a fifo.
        !           142:  */
        !           143: /* ARGSUSED */
        !           144: int
        !           145: fifo_open(void *v)
        !           146: {
        !           147:        struct vop_open_args *ap = v;
        !           148:        struct vnode *vp = ap->a_vp;
        !           149:        struct fifoinfo *fip;
        !           150:        struct proc *p = ap->a_p;
        !           151:        struct socket *rso, *wso;
        !           152:        int error;
        !           153:
        !           154:        if ((fip = vp->v_fifoinfo) == NULL) {
        !           155:                MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
        !           156:                vp->v_fifoinfo = fip;
        !           157:                if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) {
        !           158:                        free(fip, M_VNODE);
        !           159:                        vp->v_fifoinfo = NULL;
        !           160:                        return (error);
        !           161:                }
        !           162:                fip->fi_readsock = rso;
        !           163:                if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) {
        !           164:                        (void)soclose(rso);
        !           165:                        free(fip, M_VNODE);
        !           166:                        vp->v_fifoinfo = NULL;
        !           167:                        return (error);
        !           168:                }
        !           169:                fip->fi_writesock = wso;
        !           170:                if ((error = unp_connect2(wso, rso)) != 0) {
        !           171:                        (void)soclose(wso);
        !           172:                        (void)soclose(rso);
        !           173:                        free(fip, M_VNODE);
        !           174:                        vp->v_fifoinfo = NULL;
        !           175:                        return (error);
        !           176:                }
        !           177:                fip->fi_readers = fip->fi_writers = 0;
        !           178:                wso->so_snd.sb_lowat = PIPE_BUF;
        !           179:                rso->so_state |= SS_CANTRCVMORE;
        !           180:        }
        !           181:        if (ap->a_mode & FREAD) {
        !           182:                fip->fi_readers++;
        !           183:                if (fip->fi_readers == 1) {
        !           184:                        fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
        !           185:                        if (fip->fi_writers > 0)
        !           186:                                wakeup(&fip->fi_writers);
        !           187:                }
        !           188:        }
        !           189:        if (ap->a_mode & FWRITE) {
        !           190:                fip->fi_writers++;
        !           191:                if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
        !           192:                        error = ENXIO;
        !           193:                        goto bad;
        !           194:                }
        !           195:                if (fip->fi_writers == 1) {
        !           196:                        fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
        !           197:                        if (fip->fi_readers > 0)
        !           198:                                wakeup(&fip->fi_readers);
        !           199:                }
        !           200:        }
        !           201:        if ((ap->a_mode & O_NONBLOCK) == 0) {
        !           202:                if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
        !           203:                        VOP_UNLOCK(vp, 0, p);
        !           204:                        error = tsleep(&fip->fi_readers,
        !           205:                            PCATCH | PSOCK, "fifor", 0);
        !           206:                        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           207:                        if (error)
        !           208:                                goto bad;
        !           209:                }
        !           210:                if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
        !           211:                        VOP_UNLOCK(vp, 0, p);
        !           212:                        error = tsleep(&fip->fi_writers,
        !           213:                            PCATCH | PSOCK, "fifow", 0);
        !           214:                        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           215:                        if (error)
        !           216:                                goto bad;
        !           217:                }
        !           218:        }
        !           219:        return (0);
        !           220: bad:
        !           221:        VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
        !           222:        return (error);
        !           223: }
        !           224:
        !           225: /*
        !           226:  * Vnode op for read
        !           227:  */
        !           228: /* ARGSUSED */
        !           229: int
        !           230: fifo_read(void *v)
        !           231: {
        !           232:        struct vop_read_args *ap = v;
        !           233:        struct uio *uio = ap->a_uio;
        !           234:        struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
        !           235:        struct proc *p = uio->uio_procp;
        !           236:        int error;
        !           237:
        !           238: #ifdef DIAGNOSTIC
        !           239:        if (uio->uio_rw != UIO_READ)
        !           240:                panic("fifo_read mode");
        !           241: #endif
        !           242:        if (uio->uio_resid == 0)
        !           243:                return (0);
        !           244:        if (ap->a_ioflag & IO_NDELAY)
        !           245:                rso->so_state |= SS_NBIO;
        !           246:        VOP_UNLOCK(ap->a_vp, 0, p);
        !           247:        error = soreceive(rso, NULL, uio, NULL, NULL, NULL);
        !           248:        vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           249:        if (ap->a_ioflag & IO_NDELAY) {
        !           250:                rso->so_state &= ~SS_NBIO;
        !           251:                if (error == EWOULDBLOCK &&
        !           252:                    ap->a_vp->v_fifoinfo->fi_writers == 0)
        !           253:                        error = 0;
        !           254:        }
        !           255:        return (error);
        !           256: }
        !           257:
        !           258: /*
        !           259:  * Vnode op for write
        !           260:  */
        !           261: /* ARGSUSED */
        !           262: int
        !           263: fifo_write(void *v)
        !           264: {
        !           265:        struct vop_write_args *ap = v;
        !           266:        struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
        !           267:        struct proc *p = ap->a_uio->uio_procp;
        !           268:        int error;
        !           269:
        !           270: #ifdef DIAGNOSTIC
        !           271:        if (ap->a_uio->uio_rw != UIO_WRITE)
        !           272:                panic("fifo_write mode");
        !           273: #endif
        !           274:        if (ap->a_ioflag & IO_NDELAY)
        !           275:                wso->so_state |= SS_NBIO;
        !           276:        VOP_UNLOCK(ap->a_vp, 0, p);
        !           277:        error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
        !           278:        vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           279:        if (ap->a_ioflag & IO_NDELAY)
        !           280:                wso->so_state &= ~SS_NBIO;
        !           281:        return (error);
        !           282: }
        !           283:
        !           284: /*
        !           285:  * Device ioctl operation.
        !           286:  */
        !           287: /* ARGSUSED */
        !           288: int
        !           289: fifo_ioctl(void *v)
        !           290: {
        !           291:        struct vop_ioctl_args *ap = v;
        !           292:        struct file filetmp;
        !           293:        int error;
        !           294:
        !           295:        if (ap->a_command == FIONBIO)
        !           296:                return (0);
        !           297:        if (ap->a_fflag & FREAD) {
        !           298:                filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
        !           299:                error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
        !           300:                if (error)
        !           301:                        return (error);
        !           302:        }
        !           303:        if (ap->a_fflag & FWRITE) {
        !           304:                filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
        !           305:                error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
        !           306:                if (error)
        !           307:                        return (error);
        !           308:        }
        !           309:        return (0);
        !           310: }
        !           311:
        !           312: /* ARGSUSED */
        !           313: int
        !           314: fifo_poll(void *v)
        !           315: {
        !           316:        struct vop_poll_args *ap = v;
        !           317:        struct file filetmp;
        !           318:        short ostate;
        !           319:        int revents = 0;
        !           320:
        !           321:        if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
        !           322:                /*
        !           323:                 * Socket and FIFO poll(2) semantics differ wrt EOF on read.
        !           324:                 * Unlike a normal socket, FIFOs don't care whether or not
        !           325:                 * SS_CANTRCVMORE is set.  To get the correct semantics we
        !           326:                 * must clear SS_CANTRCVMORE from so_state temporarily.
        !           327:                 */
        !           328:                ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state;
        !           329:                if (ap->a_events & (POLLIN | POLLRDNORM))
        !           330:                        ap->a_vp->v_fifoinfo->fi_readsock->so_state &=
        !           331:                            ~SS_CANTRCVMORE;
        !           332:                filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
        !           333:                if (filetmp.f_data)
        !           334:                        revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
        !           335:                ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate;
        !           336:        }
        !           337:        if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
        !           338:                filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
        !           339:                if (filetmp.f_data)
        !           340:                        revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
        !           341:        }
        !           342:        return (revents);
        !           343: }
        !           344:
        !           345: int
        !           346: fifo_inactive(void *v)
        !           347: {
        !           348:        struct vop_inactive_args *ap = v;
        !           349:
        !           350:        VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
        !           351:        return (0);
        !           352: }
        !           353:
        !           354: /*
        !           355:  * This is a noop, simply returning what one has been given.
        !           356:  */
        !           357: int
        !           358: fifo_bmap(void *v)
        !           359: {
        !           360:        struct vop_bmap_args *ap = v;
        !           361:
        !           362:        if (ap->a_vpp != NULL)
        !           363:                *ap->a_vpp = ap->a_vp;
        !           364:        if (ap->a_bnp != NULL)
        !           365:                *ap->a_bnp = ap->a_bn;
        !           366:        return (0);
        !           367: }
        !           368:
        !           369: /*
        !           370:  * Device close routine
        !           371:  */
        !           372: /* ARGSUSED */
        !           373: int
        !           374: fifo_close(void *v)
        !           375: {
        !           376:        struct vop_close_args *ap = v;
        !           377:        struct vnode *vp = ap->a_vp;
        !           378:        struct fifoinfo *fip = vp->v_fifoinfo;
        !           379:        int error1 = 0, error2 = 0;
        !           380:
        !           381:        if (fip == NULL)
        !           382:                return (0);
        !           383:
        !           384:        if (ap->a_fflag & FREAD) {
        !           385:                if (--fip->fi_readers == 0)
        !           386:                        socantsendmore(fip->fi_writesock);
        !           387:        }
        !           388:        if (ap->a_fflag & FWRITE) {
        !           389:                if (--fip->fi_writers == 0)
        !           390:                        socantrcvmore(fip->fi_readsock);
        !           391:        }
        !           392:        if (fip->fi_readers == 0 && fip->fi_writers == 0) {
        !           393:                error1 = soclose(fip->fi_readsock);
        !           394:                error2 = soclose(fip->fi_writesock);
        !           395:                FREE(fip, M_VNODE);
        !           396:                vp->v_fifoinfo = NULL;
        !           397:        }
        !           398:        return (error1 ? error1 : error2);
        !           399: }
        !           400:
        !           401: int
        !           402: fifo_reclaim(void *v)
        !           403: {
        !           404:        struct vop_reclaim_args *ap = v;
        !           405:        struct vnode *vp = ap->a_vp;
        !           406:        struct fifoinfo *fip = vp->v_fifoinfo;
        !           407:
        !           408:        if (fip == NULL)
        !           409:                return (0);
        !           410:
        !           411:        soclose(fip->fi_readsock);
        !           412:        soclose(fip->fi_writesock);
        !           413:        FREE(fip, M_VNODE);
        !           414:        vp->v_fifoinfo = NULL;
        !           415:
        !           416:        return (0);
        !           417: }
        !           418:
        !           419: /*
        !           420:  * Print out the contents of a fifo vnode.
        !           421:  */
        !           422: int
        !           423: fifo_print(void *v)
        !           424: {
        !           425:        struct vop_print_args *ap = v;
        !           426:
        !           427:        printf("tag VT_NON");
        !           428:        fifo_printinfo(ap->a_vp);
        !           429:        printf("\n");
        !           430:        return 0;
        !           431: }
        !           432:
        !           433: /*
        !           434:  * Print out internal contents of a fifo vnode.
        !           435:  */
        !           436: void
        !           437: fifo_printinfo(struct vnode *vp)
        !           438: {
        !           439:        struct fifoinfo *fip = vp->v_fifoinfo;
        !           440:
        !           441:        printf(", fifo with %ld readers and %ld writers",
        !           442:                fip->fi_readers, fip->fi_writers);
        !           443: }
        !           444:
        !           445: /*
        !           446:  * Return POSIX pathconf information applicable to fifo's.
        !           447:  */
        !           448: int
        !           449: fifo_pathconf(void *v)
        !           450: {
        !           451:        struct vop_pathconf_args *ap = v;
        !           452:
        !           453:        switch (ap->a_name) {
        !           454:        case _PC_LINK_MAX:
        !           455:                *ap->a_retval = LINK_MAX;
        !           456:                return (0);
        !           457:        case _PC_PIPE_BUF:
        !           458:                *ap->a_retval = PIPE_BUF;
        !           459:                return (0);
        !           460:        case _PC_CHOWN_RESTRICTED:
        !           461:                *ap->a_retval = 1;
        !           462:                return (0);
        !           463:        default:
        !           464:                return (EINVAL);
        !           465:        }
        !           466:        /* NOTREACHED */
        !           467: }
        !           468:
        !           469: /*
        !           470:  * Fifo failed operation
        !           471:  */
        !           472: /*ARGSUSED*/
        !           473: int
        !           474: fifo_ebadf(void *v)
        !           475: {
        !           476:
        !           477:        return (EBADF);
        !           478: }
        !           479:
        !           480: /*
        !           481:  * Fifo advisory byte-level locks.
        !           482:  */
        !           483: /* ARGSUSED */
        !           484: int
        !           485: fifo_advlock(void *v)
        !           486: {
        !           487:        return (EOPNOTSUPP);
        !           488: }
        !           489:
        !           490: /*
        !           491:  * Fifo bad operation
        !           492:  */
        !           493: /*ARGSUSED*/
        !           494: int
        !           495: fifo_badop(void *v)
        !           496: {
        !           497:
        !           498:        panic("fifo_badop called");
        !           499:        /* NOTREACHED */
        !           500:        return(0);
        !           501: }
        !           502:
        !           503:
        !           504: int
        !           505: fifo_kqfilter(void *v)
        !           506: {
        !           507:        struct vop_kqfilter_args *ap = v;
        !           508:        struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
        !           509:        struct sockbuf *sb;
        !           510:
        !           511:        switch (ap->a_kn->kn_filter) {
        !           512:        case EVFILT_READ:
        !           513:                ap->a_kn->kn_fop = &fiforead_filtops;
        !           514:                sb = &so->so_rcv;
        !           515:                break;
        !           516:        case EVFILT_WRITE:
        !           517:                ap->a_kn->kn_fop = &fifowrite_filtops;
        !           518:                sb = &so->so_snd;
        !           519:                break;
        !           520:        default:
        !           521:                return (1);
        !           522:        }
        !           523:
        !           524:        ap->a_kn->kn_hook = so;
        !           525:
        !           526:        SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
        !           527:        sb->sb_flags |= SB_KNOTE;
        !           528:
        !           529:        return (0);
        !           530: }
        !           531:
        !           532: void
        !           533: filt_fifordetach(struct knote *kn)
        !           534: {
        !           535:        struct socket *so = (struct socket *)kn->kn_hook;
        !           536:
        !           537:        SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
        !           538:        if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
        !           539:                so->so_rcv.sb_flags &= ~SB_KNOTE;
        !           540: }
        !           541:
        !           542: int
        !           543: filt_fiforead(struct knote *kn, long hint)
        !           544: {
        !           545:        struct socket *so = (struct socket *)kn->kn_hook;
        !           546:
        !           547:        kn->kn_data = so->so_rcv.sb_cc;
        !           548:        if (so->so_state & SS_CANTRCVMORE) {
        !           549:                kn->kn_flags |= EV_EOF;
        !           550:                return (1);
        !           551:        }
        !           552:        kn->kn_flags &= ~EV_EOF;
        !           553:        return (kn->kn_data > 0);
        !           554: }
        !           555:
        !           556: void
        !           557: filt_fifowdetach(struct knote *kn)
        !           558: {
        !           559:        struct socket *so = (struct socket *)kn->kn_hook;
        !           560:
        !           561:        SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
        !           562:        if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
        !           563:                so->so_snd.sb_flags &= ~SB_KNOTE;
        !           564: }
        !           565:
        !           566: int
        !           567: filt_fifowrite(struct knote *kn, long hint)
        !           568: {
        !           569:        struct socket *so = (struct socket *)kn->kn_hook;
        !           570:
        !           571:        kn->kn_data = sbspace(&so->so_snd);
        !           572:        if (so->so_state & SS_CANTSENDMORE) {
        !           573:                kn->kn_flags |= EV_EOF;
        !           574:                return (1);
        !           575:        }
        !           576:        kn->kn_flags &= ~EV_EOF;
        !           577:        return (kn->kn_data >= so->so_snd.sb_lowat);
        !           578: }

CVSweb