int evfilt_timer_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; struct itimerspec ts; int tfd; kn->kev.flags |= EV_CLEAR; tfd = timerfd_create(CLOCK_MONOTONIC, 0); if (tfd < 0) { dbg_printf("timerfd_create(2): %s", strerror(errno)); return (-1); } dbg_printf("created timerfd %d", tfd); convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); if (timerfd_settime(tfd, 0, &ts, NULL) < 0) { dbg_printf("timerfd_settime(2): %s", strerror(errno)); close(tfd); return (-1); } memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN; ev.data.ptr = kn; if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, tfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %d", errno); close(tfd); return (-1); } kn->data.pfd = tfd; return (0); }
int evfilt_read_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; if (linux_get_descriptor_type(kn) < 0) return (-1); /* Convert the kevent into an epoll_event */ #if defined(HAVE_EPOLLRDHUP) kn->data.events = EPOLLIN | EPOLLRDHUP; #else kn->data.events = EPOLLIN; #endif if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) kn->data.events |= EPOLLONESHOT; if (kn->kev.flags & EV_CLEAR) kn->data.events |= EPOLLET; memset(&ev, 0, sizeof(ev)); ev.events = kn->data.events; ev.data.ptr = kn; /* Special case: for regular files, add a surrogate eventfd that is always readable */ if (kn->kn_flags & KNFL_FILE) { int evfd; kn->kn_epollfd = filter_epfd(filt); evfd = eventfd(0, 0); if (evfd < 0) { dbg_perror("eventfd(2)"); return (-1); } if (eventfd_write(evfd, 1) < 0) { dbg_perror("eventfd_write(3)"); (void) close(evfd); return (-1); } kn->kdata.kn_eventfd = evfd; if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); return (-1); } kn->kn_registered = 1; return (0); } return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); }
static int delete_watch(struct filter *filt, struct knote *kn) { int ifd = kn->kdata.kn_inotifyfd; if (ifd < 0) return (0); if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, ifd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } (void) close(ifd); kn->kdata.kn_inotifyfd = -1; return (0); }
int evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) { int rv = 0; if (kn->data.pfd == -1) return (0); if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); rv = -1; } if (close(kn->data.pfd) < 0) { dbg_printf("close(2): %s", strerror(errno)); rv = -1; } kn->data.pfd = -1; return (rv); }
static int add_watch(struct filter *filt, struct knote *kn) { struct epoll_event ev; int ifd; char path[PATH_MAX]; uint32_t mask; /* Convert the fd to a pathname */ if (linux_fd_to_path(&path[0], sizeof(path), kn->kev.ident) < 0) return (-1); /* Convert the fflags to the inotify mask */ mask = IN_CLOSE; if (kn->kev.fflags & NOTE_DELETE) mask |= IN_ATTRIB | IN_DELETE_SELF; if (kn->kev.fflags & NOTE_WRITE) mask |= IN_MODIFY | IN_ATTRIB; if (kn->kev.fflags & NOTE_EXTEND) mask |= IN_MODIFY | IN_ATTRIB; if ((kn->kev.fflags & NOTE_ATTRIB) || (kn->kev.fflags & NOTE_LINK)) mask |= IN_ATTRIB; if (kn->kev.fflags & NOTE_RENAME) mask |= IN_MOVE_SELF; if (kn->kev.flags & EV_ONESHOT) mask |= IN_ONESHOT; /* Create an inotify descriptor */ ifd = inotify_init(); if (ifd < 0) { dbg_perror("inotify_init(2)"); return (-1); } /* Add the watch */ dbg_printf("inotify_add_watch(2); inofd=%d, %s, path=%s", ifd, inotify_mask_dump(mask), path); kn->kev.data = inotify_add_watch(ifd, path, mask); if (kn->kev.data < 0) { dbg_perror("inotify_add_watch(2)"); goto errout; } /* Add the inotify fd to the epoll set */ memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN; ev.data.ptr = kn; if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, ifd, &ev) < 0) { dbg_perror("epoll_ctl(2)"); goto errout; } kn->kdata.kn_inotifyfd = ifd; return (0); errout: kn->kdata.kn_inotifyfd = -1; (void) close(ifd); return (-1); }