]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/journal/sd-journal.c
journal: store NE hash instead of LE hash in Match object
[thirdparty/systemd.git] / src / journal / sd-journal.c
index bced8af3e3abb20208f604319b0082a095a6813b..7e958e9f43140dc9476a68f17bb3f0cd082449e0 100644 (file)
@@ -45,7 +45,9 @@
 
 #define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC)
 
-#define REPLACE_VAR_MAX 256
+/* The maximum size of variable values we'll expand in catalog entries. We bind this to PATH_MAX for now, as
+ * we want to be able to show all officially valid paths at least */
+#define REPLACE_VAR_MAX PATH_MAX
 
 #define DEFAULT_DATA_THRESHOLD (64*1024)
 
@@ -115,28 +117,24 @@ static void detach_location(sd_journal *j) {
                 journal_file_reset_location(f);
 }
 
-static void reset_location(sd_journal *j) {
-        assert(j);
-
-        detach_location(j);
-        zero(j->current_location);
-}
-
 static void init_location(Location *l, LocationType type, JournalFile *f, Object *o) {
         assert(l);
         assert(IN_SET(type, LOCATION_DISCRETE, LOCATION_SEEK));
         assert(f);
-        assert(o->object.type == OBJECT_ENTRY);
-
-        l->type = type;
-        l->seqnum = le64toh(o->entry.seqnum);
-        l->seqnum_id = f->header->seqnum_id;
-        l->realtime = le64toh(o->entry.realtime);
-        l->monotonic = le64toh(o->entry.monotonic);
-        l->boot_id = o->entry.boot_id;
-        l->xor_hash = le64toh(o->entry.xor_hash);
 
-        l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
+        *l = (Location) {
+                .type = type,
+                .seqnum = le64toh(o->entry.seqnum),
+                .seqnum_id = f->header->seqnum_id,
+                .realtime = le64toh(o->entry.realtime),
+                .monotonic = le64toh(o->entry.monotonic),
+                .boot_id = o->entry.boot_id,
+                .xor_hash = le64toh(o->entry.xor_hash),
+                .seqnum_set = true,
+                .realtime_set = true,
+                .monotonic_set = true,
+                .xor_hash_set = true,
+        };
 }
 
 static void set_location(sd_journal *j, JournalFile *f, Object *o) {
@@ -242,7 +240,7 @@ static void match_free_if_empty(Match *m) {
 
 _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) {
         Match *l3, *l4, *add_here = NULL, *m;
-        le64_t le_hash;
+        uint64_t hash;
 
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
@@ -281,7 +279,7 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
         assert(j->level1->type == MATCH_OR_TERM);
         assert(j->level2->type == MATCH_AND_TERM);
 
-        le_hash = htole64(hash64(data, size));
+        hash = hash64(data, size);
 
         LIST_FOREACH(matches, l3, j->level2->matches) {
                 assert(l3->type == MATCH_OR_TERM);
@@ -291,7 +289,7 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
 
                         /* Exactly the same match already? Then ignore
                          * this addition */
-                        if (l4->le_hash == le_hash &&
+                        if (l4->hash == hash &&
                             l4->size == size &&
                             memcmp(l4->data, data, size) == 0)
                                 return 0;
@@ -317,7 +315,7 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
         if (!m)
                 goto fail;
 
-        m->le_hash = le_hash;
+        m->hash = hash;
         m->size = size;
         m->data = memdup(data, size);
         if (!m->data)
@@ -435,7 +433,7 @@ _public_ void sd_journal_flush_matches(sd_journal *j) {
         detach_location(j);
 }
 
-_pure_ static int compare_with_location(JournalFile *f, Location *l) {
+_pure_ static int compare_with_location(const JournalFile *f, const Location *l, const JournalFile *current_file) {
         int r;
 
         assert(f);
@@ -448,7 +446,8 @@ _pure_ static int compare_with_location(JournalFile *f, Location *l) {
             l->realtime_set &&
             f->current_realtime == l->realtime &&
             l->xor_hash_set &&
-            f->current_xor_hash == l->xor_hash)
+            f->current_xor_hash == l->xor_hash &&
+            f != current_file)
                 return 0;
 
         if (l->seqnum_set &&
@@ -504,7 +503,7 @@ static int next_for_match(
         if (m->type == MATCH_DISCRETE) {
                 uint64_t dp;
 
-                r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
+                r = journal_file_find_data_object_with_hash(f, m->data, m->size, m->hash, NULL, &dp);
                 if (r <= 0)
                         return r;
 
@@ -593,7 +592,7 @@ static int find_location_for_match(
         if (m->type == MATCH_DISCRETE) {
                 uint64_t dp;
 
-                r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
+                r = journal_file_find_data_object_with_hash(f, m->data, m->size, m->hash, NULL, &dp);
                 if (r <= 0)
                         return r;
 
@@ -787,7 +786,7 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
                 if (j->current_location.type == LOCATION_DISCRETE) {
                         int k;
 
-                        k = compare_with_location(f, &j->current_location);
+                        k = compare_with_location(f, &j->current_location, j->current_file);
 
                         found = direction == DIRECTION_DOWN ? k > 0 : k < 0;
                 } else
@@ -1013,9 +1012,10 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
             !realtime_set)
                 return -EINVAL;
 
-        reset_location(j);
-
-        j->current_location.type = LOCATION_SEEK;
+        detach_location(j);
+        j->current_location = (Location) {
+                .type = LOCATION_SEEK,
+        };
 
         if (realtime_set) {
                 j->current_location.realtime = (uint64_t) realtime;
@@ -1128,11 +1128,14 @@ _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, u
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
 
-        reset_location(j);
-        j->current_location.type = LOCATION_SEEK;
-        j->current_location.boot_id = boot_id;
-        j->current_location.monotonic = usec;
-        j->current_location.monotonic_set = true;
+        detach_location(j);
+
+        j->current_location = (Location) {
+                .type = LOCATION_SEEK,
+                .boot_id = boot_id,
+                .monotonic = usec,
+                .monotonic_set = true,
+        };
 
         return 0;
 }
@@ -1141,10 +1144,13 @@ _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
 
-        reset_location(j);
-        j->current_location.type = LOCATION_SEEK;
-        j->current_location.realtime = usec;
-        j->current_location.realtime_set = true;
+        detach_location(j);
+
+        j->current_location = (Location) {
+                .type = LOCATION_SEEK,
+                .realtime = usec,
+                .realtime_set = true,
+        };
 
         return 0;
 }
@@ -1153,8 +1159,11 @@ _public_ int sd_journal_seek_head(sd_journal *j) {
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
 
-        reset_location(j);
-        j->current_location.type = LOCATION_HEAD;
+        detach_location(j);
+
+        j->current_location = (Location) {
+                .type = LOCATION_HEAD,
+        };
 
         return 0;
 }
@@ -1163,8 +1172,11 @@ _public_ int sd_journal_seek_tail(sd_journal *j) {
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
 
-        reset_location(j);
-        j->current_location.type = LOCATION_TAIL;
+        detach_location(j);
+
+        j->current_location = (Location) {
+                .type = LOCATION_TAIL,
+        };
 
         return 0;
 }
@@ -1625,9 +1637,10 @@ static int add_directory(
             !((dirname && dirname_is_machine_id(dirname) > 0) || path_has_prefix(j, path, "/run")))
                 return 0;
 
-        if (!(FLAGS_SET(j->flags, SD_JOURNAL_ALL_NAMESPACES) ||
-              dirname_has_namespace(dirname, j->namespace) > 0 ||
-              (FLAGS_SET(j->flags, SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE) && dirname_has_namespace(dirname, NULL) > 0)))
+        if (dirname &&
+            (!(FLAGS_SET(j->flags, SD_JOURNAL_ALL_NAMESPACES) ||
+               dirname_has_namespace(dirname, j->namespace) > 0 ||
+               (FLAGS_SET(j->flags, SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE) && dirname_has_namespace(dirname, NULL) > 0))))
                 return 0;
 
         r = directory_open(j, path, &d);
@@ -1717,7 +1730,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
                         goto fail;
                 }
         } else {
-                int dfd;
+                _cleanup_close_ int dfd = -1;
 
                 /* 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. */
@@ -1730,10 +1743,9 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
                         goto fail;
                 }
 
-                d = fdopendir(dfd);
+                d = take_fdopendir(&dfd);
                 if (!d) {
                         r = -errno;
-                        safe_close(dfd);
                         goto fail;
                 }
 
@@ -2356,7 +2368,10 @@ static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **da
         uint64_t l;
         int compression;
 
-        l = le64toh(o->object.size) - offsetof(Object, data.payload);
+        l = le64toh(READ_NOW(o->object.size));
+        if (l < offsetof(Object, data.payload))
+                return -EBADMSG;
+        l -= offsetof(Object, data.payload);
         t = (size_t) l;
 
         /* We can't read objects larger than 4G on a 32bit machine */
@@ -2661,6 +2676,8 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
         assert_return(!journal_pid_changed(j), -ECHILD);
 
         if (j->inotify_fd < 0) {
+                Iterator i;
+                JournalFile *f;
 
                 /* This is the first invocation, hence create the
                  * inotify watch */
@@ -2668,6 +2685,18 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
                 if (r < 0)
                         return r;
 
+                /* Server might have done some vacuuming while we weren't watching.
+                   Get rid of the deleted files now so they don't stay around indefinitely. */
+                ORDERED_HASHMAP_FOREACH(f, j->files, i) {
+                        r = journal_file_fstat(f);
+                        if (r == -EIDRM)
+                                remove_file_real(j, f);
+                        else if (r < 0) {
+                                log_debug_errno(r,"Failed to fstat() journal file '%s' : %m", f->path);
+                                continue;
+                        }
+                }
+
                 /* The journal might have changed since the context
                  * object was created and we weren't watching before,
                  * hence don't wait for anything, and return