diff --git a/05-inotify/inotify.c b/05-inotify/inotify.c
index 7db4799..8b81d4a 100644
--- a/05-inotify/inotify.c
+++ b/05-inotify/inotify.c
@@ -54,9 +54,76 @@ int main(void) {
void *buffer = malloc(4096);
if (!buffer) return -1;
- // FIXME: Create Inotify Object (into inotify_fd)
- // FIXME: Add new watch to that event (result into watch_fd)
- // FIXME: Use read() and the buffer to retrieve results from the inotify_fd
+ int inotify_fd, watch_fd;
+ // First, we create a new in-kernel inotify object. As a result,
+ // we get a file descriptor as a handle for that event. Usually,
+ // this should not fail, but better safe than sorry.
+ inotify_fd = inotify_init();
+ if (inotify_fd == -1) {
+ perror("inotify_init");
+ return -1;
+ }
+
+ // We watch the current working directory ('.') and we listen on
+ // all OPEN, ACCESS and CLOSE events. This does not imply that the
+ // retrieved events do not have more flags set, but that they have
+ // at least one of the given bits set.
+ watch_fd = inotify_add_watch(inotify_fd, ".",
+ IN_OPEN | IN_ACCESS | IN_CLOSE);
+ if (watch_fd == -1) {
+ perror("inotify_add_watch");
+ return -1;
+ }
+
+
+ // OK, now we set up everything and we can start reading events
+ // from the inotify object.
+ while (true) {
+ // As the man page states, we have to use read to wait for new
+ // events (blocking) and retrieve them from the kernel. Here
+ // it is important that we use a buffer that is larger than
+ // `struct inotify_event` as a single event is usually larger
+ // as it also includes the filename as a variable-length
+ // struct field at the end.
+ int length = read(inotify_fd, buffer, 4096);
+ if (length < 0) {
+ perror("inotify/read");
+ break;
+ }
+
+ // At this point, buffer *can* contain multiple inotify
+ // events. Therefore, we have to loop over the buffer.
+ // However, as our entries are of variable length, we cannot
+ // use regular array-based pointer arithmetic.
+ for (
+ // Init: We start with an event pointer pointing to buffer[0]
+ struct inotify_event *event = buffer;
+ // Cond: As long as the event-pointer points into our buffer, we are still iterating.
+ (void*)event < buffer + length;
+ // Step: After the loop, we increase the event-pointer by the size of the inotify_event PLUS the length of the following filename)
+ event = ((void*) event) + sizeof(struct inotify_event) + event->len) {
+
+ // Now that event points to an event, we print one line for each event:
+ if (event->len)
+ printf("./%s [", event->name); // <- The filename
+ else
+ printf(". ["); // The watched directory itself
+
+ // We decode the mask field, by iterating over the
+ // flag--string table and check if the specified bit is
+ // set in the event->mask. delim is used to properly
+ // insert commas.
+ char *delim = "";
+ for (unsigned int i = 0; i < ARRAY_SIZE(inotify_event_flags); i++) {
+ if (event->mask & inotify_event_flags[i].mask) {
+ printf("%s%s", delim,
+ inotify_event_flags[i].name);
+ delim = ",";
+ }
+ }
+ printf("]\n");
+ }
+ }
// As we are nice, we free the buffer again.
free(buffer);
return 0;