[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

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