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;