From 0301256c7ae332979e3bca3d5a5e4010ba0b22eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Mon, 24 Sep 2018 21:40:05 +0200 Subject: First commit --- watch.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 watch.c diff --git a/watch.c b/watch.c new file mode 100644 index 0000000..d9e843e --- /dev/null +++ b/watch.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define fail() exit(EXIT_FAILURE) +#define fail_clean() do { status = EXIT_FAILURE; goto finally; } while (0) + +int main(int argc, char *argv[]) { + int status = EXIT_SUCCESS; + int fd, kq, n, i; + struct kevent event; + + setbuf(stdout, NULL); // disable buffering even non-interactively + + if (argc < 2) { + fprintf(stderr, "usage: %s file\n", argv[0]); + fail(); + } + + // 1. Open file + if ((fd = open(argv[1], O_RDONLY)) == -1) { + perror(argv[1]); + fail(); + } + + if ((kq = kqueue()) == -1) { + perror("kqueue"); + fail_clean(); + } + + struct kevent change = { // event to watch for + .ident = fd, + .filter = EVFILT_VNODE, + .flags = EV_ADD | EV_CLEAR, + .fflags = NOTE_WRITE | NOTE_RENAME | NOTE_DELETE, + .data = 0, + .udata = NULL + }; + + // 2. Register event to watch for + if (kevent(kq, &change, 1, NULL, 0, NULL) == -1) { + perror("kevent"); + fail_clean(); + } + if (change.flags & EV_ERROR) { + fprintf(stderr, "Event error: %s", strerror(change.data)); + fail_clean(); + } + + while (1) { + // 3. Wait for event + if ((n = kevent(kq, NULL, 0, &event, 1, NULL)) != 1) { + perror("kevent wait"); + fail_clean(); + } else if (n > 0) { + if (event.fflags & NOTE_WRITE) { + printf("%s\n", argv[1]); + } + if (event.fflags & NOTE_RENAME) + fprintf(stderr, "Note: file was renamed\n"); + if (event.fflags & NOTE_DELETE) { + fprintf(stderr, "Error: file was deleted\n"); + fail_clean(); + } + } + } + +finally: + if (close(kq) == -1) { + perror("close"); + fail(); + } + if (close(fd) == -1) { + perror("close"); + fail(); + } + + exit(status); +} -- cgit v1.2.3