]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/journal/sd-journal.c
build-sys: use #if Y instead of #ifdef Y everywhere
[thirdparty/systemd.git] / src / journal / sd-journal.c
index 6ff1c67f5fce1c59a296a5a27cc65a4c610e54be..40805eb2b8d8d170206c89269425a6dfd8bba131 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <linux/magic.h>
 #include <poll.h>
 #include <stddef.h>
@@ -34,7 +35,7 @@
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "fileio.h"
-#include "formats-util.h"
+#include "format-util.h"
 #include "fs-util.h"
 #include "hashmap.h"
 #include "hostname-util.h"
@@ -68,7 +69,7 @@ static bool journal_pid_changed(sd_journal *j) {
         /* We don't support people creating a journal object and
          * keeping it around over a fork(). Let's complain. */
 
-        return j->original_pid != getpid();
+        return j->original_pid != getpid_cached();
 }
 
 static int journal_put_error(sd_journal *j, int r, const char *path) {
@@ -135,7 +136,7 @@ static void reset_location(sd_journal *j) {
 
 static void init_location(Location *l, LocationType type, JournalFile *f, Object *o) {
         assert(l);
-        assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
+        assert(IN_SET(type, LOCATION_DISCRETE, LOCATION_SEEK));
         assert(f);
         assert(o->object.type == OBJECT_ENTRY);
 
@@ -386,7 +387,7 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) {
 }
 
 static char *match_make_string(Match *m) {
-        char *p, *r;
+        char *p = NULL, *r;
         Match *i;
         bool enclose = false;
 
@@ -396,18 +397,15 @@ static char *match_make_string(Match *m) {
         if (m->type == MATCH_DISCRETE)
                 return strndup(m->data, m->size);
 
-        p = NULL;
         LIST_FOREACH(matches, i, m->matches) {
                 char *t, *k;
 
                 t = match_make_string(i);
-                if (!t) {
-                        free(p);
-                        return NULL;
-                }
+                if (!t)
+                        return mfree(p);
 
                 if (p) {
-                        k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL);
+                        k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t);
                         free(p);
                         free(t);
 
@@ -422,7 +420,7 @@ static char *match_make_string(Match *m) {
         }
 
         if (enclose) {
-                r = strjoin("(", p, ")", NULL);
+                r = strjoin("(", p, ")");
                 free(p);
                 return r;
         }
@@ -884,8 +882,11 @@ static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t
         if (skip == 0) {
                 /* If this is not a discrete skip, then at least
                  * resolve the current location */
-                if (j->current_location.type != LOCATION_DISCRETE)
-                        return real_journal_next(j, direction);
+                if (j->current_location.type != LOCATION_DISCRETE) {
+                        r = real_journal_next(j, direction);
+                        if (r < 0)
+                                return r;
+                }
 
                 return 0;
         }
@@ -1063,7 +1064,7 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
         if (r < 0)
                 return r;
 
-        for(;;) {
+        for (;;) {
                 _cleanup_free_ char *item = NULL;
                 unsigned long long ll;
                 sd_id128_t id;
@@ -1232,14 +1233,37 @@ static bool file_type_wanted(int flags, const char *filename) {
         return false;
 }
 
-static int add_any_file(sd_journal *j, const char *path) {
+static bool path_has_prefix(sd_journal *j, const char *path, const char *prefix) {
+        assert(j);
+        assert(path);
+        assert(prefix);
+
+        if (j->toplevel_fd >= 0)
+                return false;
+
+        return path_startswith(path, prefix);
+}
+
+static const char *skip_slash(const char *p) {
+
+        if (!p)
+                return NULL;
+
+        while (*p == '/')
+                p++;
+
+        return p;
+}
+
+static int add_any_file(sd_journal *j, int fd, const char *path) {
         JournalFile *f = NULL;
+        bool close_fd = false;
         int r, k;
 
         assert(j);
-        assert(path);
+        assert(fd >= 0 || path);
 
-        if (ordered_hashmap_get(j->files, path))
+        if (path && ordered_hashmap_get(j->files, path))
                 return 0;
 
         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
@@ -1248,8 +1272,24 @@ static int add_any_file(sd_journal *j, const char *path) {
                 goto fail;
         }
 
-        r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, NULL, &f);
+        if (fd < 0 && j->toplevel_fd >= 0) {
+
+                /* If there's a top-level fd defined, open the file relative to this now. (Make the path relative,
+                 * explicitly, since otherwise openat() ignores the first argument.) */
+
+                fd = openat(j->toplevel_fd, skip_slash(path), O_RDONLY|O_CLOEXEC);
+                if (fd < 0) {
+                        r = log_debug_errno(errno, "Failed to open journal file %s: %m", path);
+                        goto fail;
+                }
+
+                close_fd = true;
+        }
+
+        r = journal_file_open(fd, path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, NULL, &f);
         if (r < 0) {
+                if (close_fd)
+                        safe_close(fd);
                 log_debug_errno(r, "Failed to open journal file %s: %m", path);
                 goto fail;
         }
@@ -1258,15 +1298,21 @@ static int add_any_file(sd_journal *j, const char *path) {
 
         r = ordered_hashmap_put(j->files, f->path, f);
         if (r < 0) {
+                f->close_fd = close_fd;
                 (void) journal_file_close(f);
                 goto fail;
         }
 
+        if (!j->has_runtime_files && path_has_prefix(j, f->path, "/run"))
+                j->has_runtime_files = true;
+        else if (!j->has_persistent_files && path_has_prefix(j, f->path, "/var"))
+                j->has_persistent_files = true;
+
         log_debug("File %s added.", f->path);
 
         check_network(j, f->fd);
 
-        j->current_invalidate_counter ++;
+        j->current_invalidate_counter++;
 
         return 0;
 
@@ -1285,18 +1331,14 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
         assert(prefix);
         assert(filename);
 
-        if (j->no_new_files ||
-            !file_type_wanted(j->flags, filename))
+        if (j->no_new_files)
                 return 0;
 
-        path = strjoina(prefix, "/", filename);
-
-        if (!j->has_runtime_files && path_startswith(path, "/run/log/journal"))
-                j->has_runtime_files = true;
-        else if (!j->has_persistent_files && path_startswith(path, "/var/log/journal"))
-                j->has_persistent_files = true;
+        if (!file_type_wanted(j->flags, filename))
+                return 0;
 
-        return add_any_file(j, path);
+        path = strjoina(prefix, "/", filename);
+        return add_any_file(j, -1, path);
 }
 
 static void remove_file(sd_journal *j, const char *prefix, const char *filename) {
@@ -1345,7 +1387,7 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
 
         (void) journal_file_close(f);
 
-        j->current_invalidate_counter ++;
+        j->current_invalidate_counter++;
 }
 
 static int dirname_is_machine_id(const char *fn) {
@@ -1372,21 +1414,33 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
 
         assert(j);
         assert(prefix);
-        assert(dirname);
-
-        log_debug("Considering %s/%s.", prefix, dirname);
 
-        if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
-            !(dirname_is_machine_id(dirname) > 0 || path_startswith(prefix, "/run")))
-            return 0;
+        /* Adds a journal file directory to watch. If the directory is already tracked this updates the inotify watch
+         * and reenumerates directory contents */
 
-        path = strjoin(prefix, "/", dirname, NULL);
+        if (dirname)
+                path = strjoin(prefix, "/", dirname);
+        else
+                path = strdup(prefix);
         if (!path) {
                 r = -ENOMEM;
                 goto fail;
         }
 
-        d = opendir(path);
+        log_debug("Considering directory %s.", path);
+
+        /* We consider everything local that is in a directory for the local machine ID, or that is stored in /run */
+        if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
+            !((dirname && dirname_is_machine_id(dirname) > 0) || path_has_prefix(j, path, "/run")))
+            return 0;
+
+
+        if (j->toplevel_fd < 0)
+                d = opendir(path);
+        else
+                /* Open the specified directory relative to the toplevel fd. Enforce that the path specified is
+                 * relative, by dropping the initial slash */
+                d = xopendirat(j->toplevel_fd, skip_slash(path), 0);
         if (!d) {
                 r = log_debug_errno(errno, "Failed to open directory %s: %m", path);
                 goto fail;
@@ -1410,7 +1464,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
                 }
 
                 path = NULL; /* avoid freeing in cleanup */
-                j->current_invalidate_counter ++;
+                j->current_invalidate_counter++;
 
                 log_debug("Directory %s added.", m->path);
 
@@ -1418,17 +1472,18 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
                 return 0;
 
         if (m->wd <= 0 && j->inotify_fd >= 0) {
+                /* Watch this directory, if it not being watched yet. */
 
-                m->wd = inotify_add_watch(j->inotify_fd, m->path,
-                                          IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
-                                          IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
-                                          IN_ONLYDIR);
+                m->wd = inotify_add_watch_fd(j->inotify_fd, dirfd(d),
+                                             IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
+                                             IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
+                                             IN_ONLYDIR);
 
                 if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
                         inotify_rm_watch(j->inotify_fd, m->wd);
         }
 
-        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
+        FOREACH_DIRENT_ALL(de, d, r = log_debug_errno(errno, "Failed to read directory %s: %m", m->path); goto fail) {
 
                 if (dirent_is_file_with_suffix(de, ".journal") ||
                     dirent_is_file_with_suffix(de, ".journal~"))
@@ -1440,7 +1495,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
         return 0;
 
 fail:
-        k = journal_put_error(j, r, path ?: dirname);
+        k = journal_put_error(j, r, path ?: prefix);
         if (k < 0)
                 return k;
 
@@ -1448,28 +1503,62 @@ fail:
 }
 
 static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
+
         _cleanup_closedir_ DIR *d = NULL;
         struct dirent *de;
         Directory *m;
         int r, k;
 
         assert(j);
-        assert(p);
 
-        if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
-            !path_startswith(p, "/run"))
-                return -EINVAL;
+        /* Adds a root directory to our set of directories to use. If the root directory is already in the set, we
+         * update the inotify logic, and renumerate the directory entries. This call may hence be called to initially
+         * populate the set, as well as to update it later. */
 
-        if (j->prefix)
-                p = strjoina(j->prefix, p);
+        if (p) {
+                /* If there's a path specified, use it. */
 
-        d = opendir(p);
-        if (!d) {
-                if (errno == ENOENT && missing_ok)
-                        return 0;
+                if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
+                    !path_has_prefix(j, p, "/run"))
+                        return -EINVAL;
 
-                r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
-                goto fail;
+                if (j->prefix)
+                        p = strjoina(j->prefix, p);
+
+                if (j->toplevel_fd < 0)
+                        d = opendir(p);
+                else
+                        d = xopendirat(j->toplevel_fd, skip_slash(p), 0);
+
+                if (!d) {
+                        if (errno == ENOENT && missing_ok)
+                                return 0;
+
+                        r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
+                        goto fail;
+                }
+        } else {
+                int dfd;
+
+                /* If there's no path specified, then we use the top-level fd itself. We duplicate the fd here, since
+                 * opendir() will take possession of the fd, and close it, which we don't want. */
+
+                p = "."; /* store this as "." in the directories hashmap */
+
+                dfd = fcntl(j->toplevel_fd, F_DUPFD_CLOEXEC, 3);
+                if (dfd < 0) {
+                        r = -errno;
+                        goto fail;
+                }
+
+                d = fdopendir(dfd);
+                if (!d) {
+                        r = -errno;
+                        safe_close(dfd);
+                        goto fail;
+                }
+
+                rewinddir(d);
         }
 
         m = hashmap_get(j->directories_by_path, p);
@@ -1481,6 +1570,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
                 }
 
                 m->is_root = true;
+
                 m->path = strdup(p);
                 if (!m->path) {
                         free(m);
@@ -1495,7 +1585,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
                         goto fail;
                 }
 
-                j->current_invalidate_counter ++;
+                j->current_invalidate_counter++;
 
                 log_debug("Root directory %s added.", m->path);
 
@@ -1504,7 +1594,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
 
         if (m->wd <= 0 && j->inotify_fd >= 0) {
 
-                m->wd = inotify_add_watch(j->inotify_fd, m->path,
+                m->wd = inotify_add_watch_fd(j->inotify_fd, dirfd(d),
                                           IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
                                           IN_ONLYDIR);
 
@@ -1515,7 +1605,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
         if (j->no_new_files)
                 return 0;
 
-        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
+        FOREACH_DIRENT_ALL(de, d, r = log_debug_errno(errno, "Failed to read directory %s: %m", m->path); goto fail) {
                 sd_id128_t id;
 
                 if (dirent_is_file_with_suffix(de, ".journal") ||
@@ -1574,6 +1664,9 @@ static int add_search_paths(sd_journal *j) {
         NULSTR_FOREACH(p, search_paths)
                 (void) add_root_directory(j, p, true);
 
+        if (!(j->flags & SD_JOURNAL_LOCAL_ONLY))
+                (void) add_root_directory(j, "/var/log/journal/remote", true);
+
         return 0;
 }
 
@@ -1584,8 +1677,7 @@ static int add_current_paths(sd_journal *j) {
         assert(j);
         assert(j->no_new_files);
 
-        /* Simply adds all directories for files we have open as
-         * "root" directories. We don't expect errors here, so we
+        /* Simply adds all directories for files we have open as directories. We don't expect errors here, so we
          * treat them as fatal. */
 
         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
@@ -1596,7 +1688,7 @@ static int add_current_paths(sd_journal *j) {
                 if (!dir)
                         return -ENOMEM;
 
-                r = add_root_directory(j, dir, true);
+                r = add_directory(j, dir, NULL);
                 if (r < 0)
                         return r;
         }
@@ -1613,13 +1705,7 @@ static int allocate_inotify(sd_journal *j) {
                         return -errno;
         }
 
-        if (!j->directories_by_wd) {
-                j->directories_by_wd = hashmap_new(NULL);
-                if (!j->directories_by_wd)
-                        return -ENOMEM;
-        }
-
-        return 0;
+        return hashmap_ensure_allocated(&j->directories_by_wd, NULL);
 }
 
 static sd_journal *journal_new(int flags, const char *path) {
@@ -1629,15 +1715,23 @@ static sd_journal *journal_new(int flags, const char *path) {
         if (!j)
                 return NULL;
 
-        j->original_pid = getpid();
+        j->original_pid = getpid_cached();
+        j->toplevel_fd = -1;
         j->inotify_fd = -1;
         j->flags = flags;
         j->data_threshold = DEFAULT_DATA_THRESHOLD;
 
         if (path) {
-                j->path = strdup(path);
-                if (!j->path)
+                char *t;
+
+                t = strdup(path);
+                if (!t)
                         goto fail;
+
+                if (flags & SD_JOURNAL_OS_ROOT)
+                        j->prefix = t;
+                else
+                        j->path = t;
         }
 
         j->files = ordered_hashmap_new(&string_hash_ops);
@@ -1653,12 +1747,17 @@ fail:
         return NULL;
 }
 
+#define OPEN_ALLOWED_FLAGS                              \
+        (SD_JOURNAL_LOCAL_ONLY |                        \
+         SD_JOURNAL_RUNTIME_ONLY |                      \
+         SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)
+
 _public_ int sd_journal_open(sd_journal **ret, int flags) {
         sd_journal *j;
         int r;
 
         assert_return(ret, -EINVAL);
-        assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL);
+        assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL);
 
         j = journal_new(flags, NULL);
         if (!j)
@@ -1677,15 +1776,21 @@ fail:
         return r;
 }
 
+#define OPEN_CONTAINER_ALLOWED_FLAGS                    \
+        (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM)
+
 _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
         _cleanup_free_ char *root = NULL, *class = NULL;
         sd_journal *j;
         char *p;
         int r;
 
+        /* This is pretty much deprecated, people should use machined's OpenMachineRootDirectory() call instead in
+         * combination with sd_journal_open_directory_fd(). */
+
         assert_return(machine, -EINVAL);
         assert_return(ret, -EINVAL);
-        assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL);
+        assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL);
         assert_return(machine_name_is_valid(machine), -EINVAL);
 
         p = strjoina("/run/systemd/machines/", machine);
@@ -1700,13 +1805,10 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
         if (!streq_ptr(class, "container"))
                 return -EIO;
 
-        j = journal_new(flags, NULL);
+        j = journal_new(flags, root);
         if (!j)
                 return -ENOMEM;
 
-        j->prefix = root;
-        root = NULL;
-
         r = add_search_paths(j);
         if (r < 0)
                 goto fail;
@@ -1719,19 +1821,26 @@ fail:
         return r;
 }
 
+#define OPEN_DIRECTORY_ALLOWED_FLAGS                    \
+        (SD_JOURNAL_OS_ROOT |                           \
+         SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+
 _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
         sd_journal *j;
         int r;
 
         assert_return(ret, -EINVAL);
         assert_return(path, -EINVAL);
-        assert_return(flags == 0, -EINVAL);
+        assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL);
 
         j = journal_new(flags, path);
         if (!j)
                 return -ENOMEM;
 
-        r = add_root_directory(j, path, false);
+        if (flags & SD_JOURNAL_OS_ROOT)
+                r = add_search_paths(j);
+        else
+                r = add_root_directory(j, path, false);
         if (r < 0)
                 goto fail;
 
@@ -1740,7 +1849,6 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
 
 fail:
         sd_journal_close(j);
-
         return r;
 }
 
@@ -1757,7 +1865,7 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
                 return -ENOMEM;
 
         STRV_FOREACH(path, paths) {
-                r = add_any_file(j, *path);
+                r = add_any_file(j, -1, *path);
                 if (r < 0)
                         goto fail;
         }
@@ -1769,7 +1877,100 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
 
 fail:
         sd_journal_close(j);
+        return r;
+}
+
+#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS         \
+        (SD_JOURNAL_OS_ROOT |                           \
+         SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+
+_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
+        sd_journal *j;
+        struct stat st;
+        int r;
+
+        assert_return(ret, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
+        assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL);
+
+        if (fstat(fd, &st) < 0)
+                return -errno;
+
+        if (!S_ISDIR(st.st_mode))
+                return -EBADFD;
+
+        j = journal_new(flags, NULL);
+        if (!j)
+                return -ENOMEM;
+
+        j->toplevel_fd = fd;
+
+        if (flags & SD_JOURNAL_OS_ROOT)
+                r = add_search_paths(j);
+        else
+                r = add_root_directory(j, NULL, false);
+        if (r < 0)
+                goto fail;
+
+        *ret = j;
+        return 0;
+
+fail:
+        sd_journal_close(j);
+        return r;
+}
+
+_public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
+        Iterator iterator;
+        JournalFile *f;
+        sd_journal *j;
+        unsigned i;
+        int r;
+
+        assert_return(ret, -EINVAL);
+        assert_return(n_fds > 0, -EBADF);
+        assert_return(flags == 0, -EINVAL);
+
+        j = journal_new(flags, NULL);
+        if (!j)
+                return -ENOMEM;
+
+        for (i = 0; i < n_fds; i++) {
+                struct stat st;
+
+                if (fds[i] < 0) {
+                        r = -EBADF;
+                        goto fail;
+                }
+
+                if (fstat(fds[i], &st) < 0) {
+                        r = -errno;
+                        goto fail;
+                }
+
+                if (!S_ISREG(st.st_mode)) {
+                        r = -EBADFD;
+                        goto fail;
+                }
+
+                r = add_any_file(j, fds[i], NULL);
+                if (r < 0)
+                        goto fail;
+        }
+
+        j->no_new_files = true;
+        j->no_inotify = true;
 
+        *ret = j;
+        return 0;
+
+fail:
+        /* If we fail, make sure we don't take possession of the files we managed to make use of successfully, and they
+         * remain open */
+        ORDERED_HASHMAP_FOREACH(f, j->files, iterator)
+                f->close_fd = false;
+
+        sd_journal_close(j);
         return r;
 }
 
@@ -1951,13 +2152,13 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
 
                 compression = o->object.flags & OBJECT_COMPRESSION_MASK;
                 if (compression) {
-#if defined(HAVE_XZ) || defined(HAVE_LZ4)
+#if HAVE_XZ || HAVE_LZ4
                         r = decompress_startswith(compression,
                                                   o->data.payload, l,
                                                   &f->compress_buffer, &f->compress_buffer_size,
                                                   field, field_length, '=');
                         if (r < 0)
-                                log_debug_errno(r, "Cannot decompress %s object of length %zu at offset "OFSfmt": %m",
+                                log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m",
                                                 object_compressed_to_string(compression), l, p);
                         else if (r > 0) {
 
@@ -2015,7 +2216,7 @@ static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **da
 
         compression = o->object.flags & OBJECT_COMPRESSION_MASK;
         if (compression) {
-#if defined(HAVE_XZ) || defined(HAVE_LZ4)
+#if HAVE_XZ || HAVE_LZ4
                 size_t rsize;
                 int r;
 
@@ -2078,7 +2279,7 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
         if (r < 0)
                 return r;
 
-        j->current_field ++;
+        j->current_field++;
 
         return 1;
 }
@@ -2096,6 +2297,9 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
 
+        if (j->no_inotify)
+                return -EMEDIUMTYPE;
+
         if (j->inotify_fd >= 0)
                 return j->inotify_fd;
 
@@ -2103,10 +2307,16 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
         if (r < 0)
                 return r;
 
+        log_debug("Reiterating files to get inotify watches established");
+
         /* Iterate through all dirs again, to add them to the
          * inotify */
         if (j->no_new_files)
                 r = add_current_paths(j);
+        else if (j->flags & SD_JOURNAL_OS_ROOT)
+                r = add_search_paths(j);
+        else if (j->toplevel_fd >= 0)
+                r = add_root_directory(j, NULL, false);
         else if (j->path)
                 r = add_root_directory(j, j->path, true);
         else
@@ -2217,6 +2427,7 @@ _public_ int sd_journal_process(sd_journal *j) {
         assert_return(!journal_pid_changed(j), -ECHILD);
 
         j->last_process_usec = now(CLOCK_MONOTONIC);
+        j->last_invalidate_counter = j->current_invalidate_counter;
 
         for (;;) {
                 union inotify_event_buffer buffer;
@@ -2225,7 +2436,7 @@ _public_ int sd_journal_process(sd_journal *j) {
 
                 l = read(j->inotify_fd, &buffer, sizeof(buffer));
                 if (l < 0) {
-                        if (errno == EAGAIN || errno == EINTR)
+                        if (IN_SET(errno, EAGAIN, EINTR))
                                 return got_something ? determine_change(j) : SD_JOURNAL_NOP;
 
                         return -errno;