diff options
-rw-r--r-- | lib/notify.c | 87 | ||||
-rw-r--r-- | lib/portability.c | 94 | ||||
-rw-r--r-- | lib/portability.h | 12 | ||||
-rw-r--r-- | toys/posix/tail.c | 7 |
4 files changed, 107 insertions, 93 deletions
diff --git a/lib/notify.c b/lib/notify.c deleted file mode 100644 index a7993e2a..00000000 --- a/lib/notify.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "toys.h" - -static char **paths; -static int *fds; -static int count; - -#ifdef __APPLE__ - -#include <sys/event.h> - -static int kq = -1; - -void notify_init(int max) -{ - if ((kq = kqueue()) == -1) perror_exit("kqueue"); - paths = xmalloc(max * sizeof(char *)); - fds = xmalloc(max * sizeof(int)); -} - -int notify_add(int fd, char *path) -{ - struct kevent event; - - EV_SET(&event, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL); - if (kevent(kq, &event, 1, NULL, 0, NULL) == -1 || event.flags & EV_ERROR) - return -1; - paths[count] = path; - fds[count++] = fd; - return 0; -} - -int notify_wait(char **path) -{ - struct kevent event; - int i; - - for (;;) { - if (kevent(kq, NULL, 0, &event, 1, NULL) != -1) { - // We get the fd for free, but still have to search for the path. - for (i=0; i<count; i++) if (fds[i]==event.ident) { - *path = paths[i]; - return event.ident; - } - } - } -} - -#else - -#include <sys/inotify.h> - -static int ffd = -1; -static int *ids; - -void notify_init(int max) -{ - if ((ffd = inotify_init()) < 0) perror_exit("inotify_init"); - fds = xmalloc(max * sizeof(int)); - ids = xmalloc(max * sizeof(int)); - paths = xmalloc(max * sizeof(char *)); -} - -int notify_add(int fd, char *path) -{ - ids[count] = inotify_add_watch(ffd, path, IN_MODIFY); - if (ids[count] == -1) return -1; - paths[count] = path; - fds[count++] = fd; - return 0; -} - -int notify_wait(char **path) -{ - struct inotify_event ev; - int i; - - for (;;) { - if (sizeof(ev)!=read(ffd, &ev, sizeof(ev))) perror_exit("inotify"); - - for (i=0; i<count; i++) if (ev.wd==ids[i]) { - *path = paths[i]; - return fds[i]; - } - } -} - -#endif diff --git a/lib/portability.c b/lib/portability.c index c75e8ba5..726e42a9 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -153,3 +153,97 @@ struct mtab_list *xgetmountlist(char *path) } #endif + +#ifdef __APPLE__ + +#include <sys/event.h> + +struct xnotify *xnotify_init(int max) +{ + struct xnotify *not = xzalloc(sizeof(struct xnotify)); + + not->max = max; + if ((not->kq = kqueue()) == -1) perror_exit("kqueue"); + not->paths = xmalloc(max * sizeof(char *)); + not->fds = xmalloc(max * sizeof(int)); + + return not; +} + +int xnotify_add(struct xnotify *not, int fd, char *path) +{ + struct kevent event; + + if (not->count == not->max) error_exit("xnotify_add overflow"); + EV_SET(&event, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL); + if (kevent(not->kq, &event, 1, NULL, 0, NULL) == -1 || event.flags & EV_ERROR) + return -1; + not->paths[not->count] = path; + not->fds[not->count++] = fd; + + return 0; +} + +int xnotify_wait(struct xnotify *not, char **path) +{ + struct kevent event; + int i; + + for (;;) { + if (kevent(not->kq, NULL, 0, &event, 1, NULL) != -1) { + // We get the fd for free, but still have to search for the path. + for (i = 0; i<not->count; i++) if (not->fds[i]==event.ident) { + *path = paths[i]; + + return event.ident; + } + } + } +} + +#else + +#include <sys/inotify.h> + +struct xnotify *xnotify_init(int max) +{ + struct xnotify *not = xzalloc(sizeof(struct xnotify)); + + not->max = max; + if ((not->kq = inotify_init()) < 0) perror_exit("inotify_init"); + not->paths = xmalloc(max * sizeof(char *)); + not->fds = xmalloc(max * 2 * sizeof(int)); + + return not; +} + +int xnotify_add(struct xnotify *not, int fd, char *path) +{ + int i = 2*not->count; + + if (not->max == not->count) error_exit("xnotify_add overflow"); + if ((not->fds[i] = inotify_add_watch(not->kq, path, IN_MODIFY))==-1) + return -1; + not->fds[i+1] = fd; + not->paths[not->count++] = path; + + return 0; +} + +int xnotify_wait(struct xnotify *not, char **path) +{ + struct inotify_event ev; + int i; + + for (;;) { + if (sizeof(ev)!=read(not->kq, &ev, sizeof(ev))) perror_exit("inotify"); + + for (i = 0; i<not->count; i++) if (ev.wd==not->fds[2*i]) { + *path = not->paths[i]; + + return not->fds[2*i+1]; + } + } +} + +#endif diff --git a/lib/portability.h b/lib/portability.h index f4a2b327..f5f8352a 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -309,6 +309,12 @@ static inline void confstr(int a, char *b, int c) {strcpy(b, a ? "POSIXLY_CORREC #endif // Paper over the differences between BSD kqueue and Linux inotify for tail. -void notify_init(int max); -int notify_add(int fd, char *path); -int notify_wait(char **path); + +struct xnotify { + char **paths; + int max, *fds, count, kq; +}; + +struct xnotify *xnotify_init(int max); +int xnotify_add(struct xnotify *not, int fd, char *path); +int xnotify_wait(struct xnotify *not, char **path); diff --git a/toys/posix/tail.c b/toys/posix/tail.c index 49a7f69b..d49a70c2 100644 --- a/toys/posix/tail.c +++ b/toys/posix/tail.c @@ -36,6 +36,7 @@ GLOBALS( long n, c; int file_no, last_fd; + struct xnotify *not; ) struct line_list { @@ -139,7 +140,7 @@ static void do_tail(int fd, char *name) char *s = name; if (!fd) sprintf(s = toybuf, "/proc/self/fd/%d", fd); - if (notify_add(fd, s) == -1) perror_exit("-f on '%s' failed", s); + if (xnotify_add(TT.not, fd, s)) perror_exit("-f on '%s' failed", s); } if (TT.file_no++) xputc('\n'); @@ -233,13 +234,13 @@ void tail_main(void) } } - if (FLAG(f)) notify_init(toys.optc); + if (FLAG(f)) TT.not = xnotify_init(toys.optc); loopfiles_rw(args, O_RDONLY|WARN_ONLY|(O_CLOEXEC*!FLAG(f)), 0, do_tail); if (FLAG(f) && TT.file_no) { for (;;) { char *path; - int fd = notify_wait(&path), len; + int fd = xnotify_wait(TT.not, &path), len; // Read new data. while ((len = read(fd, toybuf, sizeof(toybuf)))>0) { |