summaryrefslogtreecommitdiff
path: root/src/fs_event
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs_event')
-rw-r--r--src/fs_event/fs_event.h26
-rw-r--r--src/fs_event/fs_event_inotify.c57
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);
+}