diff options
Diffstat (limited to 'src/fs_event')
| -rw-r--r-- | src/fs_event/fs_event.h | 26 | ||||
| -rw-r--r-- | src/fs_event/fs_event_inotify.c | 57 |
2 files changed, 83 insertions, 0 deletions
diff --git a/src/fs_event/fs_event.h b/src/fs_event/fs_event.h new file mode 100644 index 0000000..0240e6f --- /dev/null +++ b/src/fs_event/fs_event.h @@ -0,0 +1,26 @@ +#pragma once + +#include <al/str.h> + +#ifndef _WIN32 +#include <sys/inotify.h> +#endif + +#include "../loop.h" + +struct aki_fs_event { + s32 fd; + u32 mask; + char *path; + s32 wd; + ev_io event; + struct aki_event_loop *loop; + void (*callback)(void *, struct inotify_event *); + void *userdata; +}; + +void aki_fs_event_init(struct aki_fs_event *fs, str *path, u32 mask, + void (*callback)(void *, struct inotify_event *), void *userdata); +bool aki_fs_event_start(struct aki_fs_event *fs, struct aki_event_loop *loop); +void aki_fs_event_stop(struct aki_fs_event *fs); +void aki_fs_event_free(struct aki_fs_event *fs); diff --git a/src/fs_event/fs_event_inotify.c b/src/fs_event/fs_event_inotify.c new file mode 100644 index 0000000..0fc19b4 --- /dev/null +++ b/src/fs_event/fs_event_inotify.c @@ -0,0 +1,57 @@ +#include <al/log.h> + +#include "../util/error.h" +#include "../socket/socket.h" + +#include "fs_event.h" + +static void event_callback(struct ev_loop *loop, ev_io *w, s32 revents) +{ + (void)loop; + struct aki_fs_event *fs = (struct aki_fs_event *)w->data; + (void)revents; + struct inotify_event event = { 0 }; + ssize_t ret = aki_read(fs->fd, &event, sizeof(struct inotify_event)); + if (ret == sizeof(struct inotify_event)) { + al_assert(event.wd == fs->wd); + al_assert(event.len == 0); + fs->callback(fs->userdata, &event); + } +} + +void aki_fs_event_init(struct aki_fs_event *fs, str *path, u32 mask, + void (*callback)(void *, struct inotify_event *), void *userdata) +{ + fs->fd = inotify_init(); + aki_fd_set_blocking(fs->fd, true); + fs->mask = mask; + fs->callback = callback; + fs->userdata = userdata; + fs->path = al_str_to_c_str(path); + fs->event.data = fs; + ev_io_init(&fs->event, event_callback, fs->fd, EV_READ); +} + +bool aki_fs_event_start(struct aki_fs_event *fs, struct aki_event_loop *loop) +{ + fs->loop = loop; + fs->wd = inotify_add_watch(fs->fd, fs->path, fs->mask); + if (fs->wd == -1) { + al_log_error("fs_event", "inotify_add_watch(%s) failed (%s)", fs->path, aki_strerror(errno)); + return false; + } + ev_io_start(fs->loop->ev, &fs->event); + return true; +} + +void aki_fs_event_stop(struct aki_fs_event *fs) +{ + inotify_rm_watch(fs->fd, fs->wd); + ev_io_stop(fs->loop->ev, &fs->event); +} + +void aki_fs_event_free(struct aki_fs_event *fs) +{ + close(fs->fd); + al_free(fs->path); +} |