chiark / gitweb /
journal: don't clobber return parameters of sd_journal_get_cutoff_realtime_usec(...
[elogind.git] / src / journal / sd-journal.c
index 2ba7ca4559988a9573f8358bf23b7e2217a7b49b..831ab6b4e9b28446812f05e02faf74a40519f096 100644 (file)
@@ -41,6 +41,7 @@
 #include "missing.h"
 #include "catalog.h"
 #include "replace-var.h"
+#include "fileio.h"
 
 #define JOURNAL_FILES_MAX 1024
 
@@ -463,7 +464,7 @@ static int compare_entry_order(JournalFile *af, Object *_ao,
 
         if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id)) {
 
-                /* If the boot id matches compare monotonic time */
+                /* If the boot id matches, compare monotonic time */
                 a = le64toh(ao->entry.monotonic);
                 b = le64toh(bo->entry.monotonic);
 
@@ -473,7 +474,7 @@ static int compare_entry_order(JournalFile *af, Object *_ao,
                         return 1;
         }
 
-        /* Otherwise compare UTC time */
+        /* Otherwise, compare UTC time */
         a = le64toh(ao->entry.realtime);
         b = le64toh(bo->entry.realtime);
 
@@ -1280,7 +1281,7 @@ static bool file_type_wanted(int flags, const char *filename) {
 }
 
 static int add_any_file(sd_journal *j, const char *path) {
-        JournalFile *f;
+        JournalFile *f = NULL;
         int r;
 
         assert(j);
@@ -1441,10 +1442,16 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
 
         for (;;) {
                 struct dirent *de;
-                union dirent_storage buf;
 
-                r = readdir_r(d, &buf.de, &de);
-                if (r != 0 || !de)
+                errno = 0;
+                de = readdir(d);
+                if (!de && errno != 0) {
+                        r = -errno;
+                        log_debug("Failed to read directory %s: %s",
+                                  m->path, strerror(errno));
+                        return r;
+                }
+                if (!de)
                         break;
 
                 if (dirent_is_file_with_suffix(de, ".journal") ||
@@ -1477,6 +1484,9 @@ static int add_root_directory(sd_journal *j, const char *p) {
             !path_startswith(p, "/run"))
                 return -EINVAL;
 
+        if (j->prefix)
+                p = strappenda(j->prefix, p);
+
         d = opendir(p);
         if (!d)
                 return -errno;
@@ -1522,11 +1532,17 @@ static int add_root_directory(sd_journal *j, const char *p) {
 
         for (;;) {
                 struct dirent *de;
-                union dirent_storage buf;
                 sd_id128_t id;
 
-                r = readdir_r(d, &buf.de, &de);
-                if (r != 0 || !de)
+                errno = 0;
+                de = readdir(d);
+                if (!de && errno != 0) {
+                        r = -errno;
+                        log_debug("Failed to read directory %s: %s",
+                                  m->path, strerror(errno));
+                        return r;
+                }
+                if (!de)
                         break;
 
                 if (dirent_is_file_with_suffix(de, ".journal") ||
@@ -1612,8 +1628,8 @@ static int add_current_paths(sd_journal *j) {
          * treat them as fatal. */
 
         HASHMAP_FOREACH(f, j->files, i) {
-                int r;
                 _cleanup_free_ char *dir;
+                int r;
 
                 dir = dirname_malloc(f->path);
                 if (!dir)
@@ -1684,12 +1700,7 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
         int r;
 
         assert_return(ret, -EINVAL);
-
-        if (flags & ~(SD_JOURNAL_LOCAL_ONLY|
-                      SD_JOURNAL_RUNTIME_ONLY|
-                      SD_JOURNAL_SYSTEM|
-                      SD_JOURNAL_CURRENT_USER))
-                return -EINVAL;
+        assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL);
 
         j = journal_new(flags, NULL);
         if (!j)
@@ -1708,6 +1719,48 @@ fail:
         return r;
 }
 
+_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;
+
+        assert_return(machine, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL);
+        assert_return(filename_is_safe(machine), -EINVAL);
+
+        p = strappenda("/run/systemd/machines/", machine);
+        r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL);
+        if (r == -ENOENT)
+                return -EHOSTDOWN;
+        if (r < 0)
+                return r;
+        if (!root)
+                return -ENODATA;
+
+        if (!streq_ptr(class, "container"))
+                return -EIO;
+
+        j = journal_new(flags, NULL);
+        if (!j)
+                return -ENOMEM;
+
+        j->prefix = root;
+        root = NULL;
+
+        r = add_search_paths(j);
+        if (r < 0)
+                goto fail;
+
+        *ret = j;
+        return 0;
+
+fail:
+        sd_journal_close(j);
+        return r;
+}
+
 _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
         sd_journal *j;
         int r;
@@ -1798,6 +1851,7 @@ _public_ void sd_journal_close(sd_journal *j) {
         }
 
         free(j->path);
+        free(j->prefix);
         free(j->unique_field);
         set_free(j->errors);
         free(j);
@@ -2293,6 +2347,7 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from,
         Iterator i;
         JournalFile *f;
         bool first = true;
+        uint64_t fmin = 0, tmax = 0;
         int r;
 
         assert_return(j, -EINVAL);
@@ -2312,19 +2367,20 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from,
                         continue;
 
                 if (first) {
-                        if (from)
-                                *from = fr;
-                        if (to)
-                                *to = t;
+                        fmin = fr;
+                        tmax = t;
                         first = false;
                 } else {
-                        if (from)
-                                *from = MIN(fr, *from);
-                        if (to)
-                                *to = MAX(t, *to);
+                        fmin = MIN(fr, fmin);
+                        tmax = MAX(t, tmax);
                 }
         }
 
+        if (from)
+                *from = fmin;
+        if (to)
+                *to = tmax;
+
         return first ? 0 : 1;
 }
 
@@ -2427,9 +2483,7 @@ _public_ int sd_journal_query_unique(sd_journal *j, const char *field) {
 }
 
 _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) {
-        Object *o;
         size_t k;
-        int r;
 
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
@@ -2449,9 +2503,11 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
         for (;;) {
                 JournalFile *of;
                 Iterator i;
+                Object *o;
                 const void *odata;
                 size_t ol;
                 bool found;
+                int r;
 
                 /* Proceed to next data object in the field's linked list */
                 if (j->unique_offset == 0) {
@@ -2488,8 +2544,16 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
                         return r;
 
                 /* Let's do the type check by hand, since we used 0 context above. */
-                if (o->object.type != OBJECT_DATA)
+                if (o->object.type != OBJECT_DATA) {
+                        log_error("%s:offset " OFSfmt ": object has type %d, expected %d",
+                                  j->unique_file->path, j->unique_offset,
+                                  o->object.type, OBJECT_DATA);
                         return -EBADMSG;
+                }
+
+                r = journal_file_object_keep(j->unique_file, o, j->unique_offset);
+                if (r < 0)
+                        return r;
 
                 r = return_data(j, j->unique_file, o, &odata, &ol);
                 if (r < 0)
@@ -2523,6 +2587,10 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
                 if (found)
                         continue;
 
+                r = journal_file_object_release(j->unique_file, o, j->unique_offset);
+                if (r < 0)
+                        return r;
+
                 r = return_data(j, j->unique_file, o, data, l);
                 if (r < 0)
                         return r;