diff --git a/src/api/dirmonitor/inodewatcher.cpp b/src/api/dirmonitor/inodewatcher.cpp new file mode 100644 index 00000000..e749f5bd --- /dev/null +++ b/src/api/dirmonitor/inodewatcher.cpp @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +struct dirmonitor_internal* init_dirmonitor(); +void deinit_dirmonitor(struct dirmonitor_internal*); +int get_changes_dirmonitor(struct dirmonitor_internal*, char*, int); +int translate_changes_dirmonitor(struct dirmonitor_internal*, char*, int, int (*)(int, const char*, void*), void*); +int add_dirmonitor(struct dirmonitor_internal*, const char*); +void remove_dirmonitor(struct dirmonitor_internal*, int); +int get_mode_dirmonitor(); +} + +struct dirmonitor_internal { + int fd; + // a pipe is used to wake the thread in case of exit + int sig[2]; +}; + + +struct dirmonitor_internal* init_dirmonitor() { + struct dirmonitor_internal* monitor = (struct dirmonitor_internal*)calloc(sizeof(struct dirmonitor_internal), 1); + monitor->fd = create_inode_watcher(0); + pipe(monitor->sig); + fcntl(monitor->sig[0], F_SETFD, FD_CLOEXEC); + fcntl(monitor->sig[1], F_SETFD, FD_CLOEXEC); + return monitor; +} + + +void deinit_dirmonitor(struct dirmonitor_internal* monitor) { + close(monitor->fd); + close(monitor->sig[0]); + close(monitor->sig[1]); +} + + + +int get_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buffer, int length) { + struct pollfd fds[2] = { { .fd = monitor->fd, .events = POLLIN | POLLERR, .revents = 0 }, { .fd = monitor->sig[0], .events = POLLIN | POLLERR, .revents = 0 } }; + poll(fds, 2, -1); + return read(monitor->fd, buffer, length); +} + + +int translate_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buffer, int length, int (*change_callback)(int, const char*, void*), void* data) { + InodeWatcherEvent* event = (InodeWatcherEvent*)buffer; + change_callback(event->watch_descriptor, NULL, data); + return 0; +} + + +int add_dirmonitor(struct dirmonitor_internal* monitor, const char* path) { + return inode_watcher_add_watch(monitor->fd, path, strlen(path), + static_cast( + InodeWatcherEvent::Type::MetadataModified | + InodeWatcherEvent::Type::ContentModified | + InodeWatcherEvent::Type::Deleted | + InodeWatcherEvent::Type::ChildCreated | + InodeWatcherEvent::Type::ChildDeleted + )); +} + + +void remove_dirmonitor(struct dirmonitor_internal* monitor, int fd) { + inode_watcher_remove_watch(monitor->fd, fd); +} + +int get_mode_dirmonitor() { return 2; } diff --git a/src/main.c b/src/main.c index 104e5fe2..d3a19b99 100644 --- a/src/main.c +++ b/src/main.c @@ -9,7 +9,7 @@ #ifdef _WIN32 #include -#elif defined(__linux__) +#elif defined(__linux__) || defined(__serenity__) #include #elif defined(__APPLE__) #include @@ -34,7 +34,7 @@ static void get_exe_filename(char *buf, int sz) { } else { buf[0] = '\0'; } -#elif __linux__ +#elif __linux__ || __serenity__ char path[] = "/proc/self/exe"; ssize_t len = readlink(path, buf, sz - 1); if (len > 0) @@ -110,6 +110,9 @@ void set_macos_bundle_resources(lua_State *L); #define ARCH_PLATFORM "freebsd" #elif __APPLE__ #define ARCH_PLATFORM "darwin" + #elif __serenity__ + #define ARCH_PLATFORM "serenity" + #else #endif #if !defined(ARCH_PROCESSOR) || !defined(ARCH_PLATFORM) diff --git a/src/meson.build b/src/meson.build index a156ae3f..501914c8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,20 +11,31 @@ lite_sources = [ 'main.c', ] +lite_sources += 'api/dirmonitor.c' # dirmonitor backend if get_option('dirmonitor_backend') == '' if cc.has_function('inotify_init', prefix : '#include') dirmonitor_backend = 'inotify' + lite_sources += 'api/dirmonitor/inotify.c' elif host_machine.system() == 'darwin' and cc.check_header('CoreServices/CoreServices.h') dirmonitor_backend = 'fsevents' + lite_sources += 'api/dirmonitor/fsevents.c' elif cc.has_function('kqueue', prefix : '#include') dirmonitor_backend = 'kqueue' + lite_sources += 'api/dirmonitor/kqueue.c' + elif cc.has_function('create_inode_watcher', prefix : '#include') + dirmonitor_backend = 'inodewatcher' + add_languages('cpp') + lite_sources += 'api/dirmonitor/inodewatcher.cpp' elif dependency('libkqueue', required : false).found() dirmonitor_backend = 'kqueue' + lite_sources += 'api/dirmonitor/kqueue.c' elif host_machine.system() == 'windows' dirmonitor_backend = 'win32' + lite_sources += 'api/dirmonitor/win32.c' else dirmonitor_backend = 'dummy' + lite_sources += 'api/dirmonitor/dummy.c' warning('no suitable backend found, defaulting to dummy backend') endif else @@ -40,12 +51,6 @@ if dirmonitor_backend == 'kqueue' endif endif -lite_sources += [ - 'api/dirmonitor.c', - 'api/dirmonitor/' + dirmonitor_backend + '.c', -] - - lite_rc = [] if host_machine.system() == 'windows' windows = import('windows')