chiark / gitweb /
sd-journal: properly parse cursor strings
[elogind.git] / src / journal / sd-journal.c
index 359a7cac3e4e6231cfc6b6c60326543275484db7..05a8445b3703f0ad737d12eeee3647cf23ec202e 100644 (file)
@@ -357,15 +357,27 @@ _public_ void sd_journal_flush_matches(sd_journal *j) {
         detach_location(j);
 }
 
-static int compare_order(JournalFile *af, Object *ao,
-                         JournalFile *bf, Object *bo) {
+static int compare_entry_order(JournalFile *af, Object *_ao,
+                         JournalFile *bf, uint64_t bp) {
 
         uint64_t a, b;
+        Object *ao, *bo;
+        int r;
 
         assert(af);
-        assert(ao);
         assert(bf);
-        assert(bo);
+        assert(_ao);
+
+        /* The mmap cache might invalidate the object from the first
+         * file if we look at the one from the second file. Hence
+         * temporarily copy the header of the first one, and look at
+         * that only. */
+        ao = alloca(offsetof(EntryObject, items));
+        memcpy(ao, _ao, offsetof(EntryObject, items));
+
+        r = journal_file_move_to_object(bf, OBJECT_ENTRY, bp, &bo);
+        if (r < 0)
+                return strcmp(af->path, bf->path);
 
         /* We operate on two different files here, hence we can access
          * two objects at the same time, which we normally can't.
@@ -808,18 +820,17 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
 }
 
 static int real_journal_next(sd_journal *j, direction_t direction) {
-        JournalFile *f, *new_current = NULL;
+        JournalFile *f, *new_file = NULL;
+        uint64_t new_offset = 0;
+        Object *o;
+        uint64_t p;
         Iterator i;
         int r;
-        uint64_t new_offset = 0;
-        Object *new_entry = NULL;
 
         if (!j)
                 return -EINVAL;
 
         HASHMAP_FOREACH(f, j->files, i) {
-                Object *o;
-                uint64_t p;
                 bool found;
 
                 r = next_beyond_location(j, f, direction, &o, &p);
@@ -829,12 +840,12 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
                 } else if (r == 0)
                         continue;
 
-                if (!new_current)
+                if (!new_file)
                         found = true;
                 else {
                         int k;
 
-                        k = compare_order(f, o, new_current, new_entry);
+                        k = compare_entry_order(f, o, new_file, new_offset);
 
                         if (direction == DIRECTION_DOWN)
                                 found = k < 0;
@@ -843,16 +854,19 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
                 }
 
                 if (found) {
-                        new_current = f;
-                        new_entry = o;
+                        new_file = f;
                         new_offset = p;
                 }
         }
 
-        if (!new_current)
+        if (!new_file)
                 return 0;
 
-        set_location(j, new_current, new_entry, new_offset);
+        r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_offset, &o);
+        if (r < 0)
+                return r;
+
+        set_location(j, new_file, o, new_offset);
 
         return 1;
 }
@@ -969,35 +983,35 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
 
                 case 's':
                         seqnum_id_set = true;
-                        k = sd_id128_from_string(w+2, &seqnum_id);
+                        k = sd_id128_from_string(item+2, &seqnum_id);
                         break;
 
                 case 'i':
                         seqnum_set = true;
-                        if (sscanf(w+2, "%llx", &seqnum) != 1)
+                        if (sscanf(item+2, "%llx", &seqnum) != 1)
                                 k = -EINVAL;
                         break;
 
                 case 'b':
                         boot_id_set = true;
-                        k = sd_id128_from_string(w+2, &boot_id);
+                        k = sd_id128_from_string(item+2, &boot_id);
                         break;
 
                 case 'm':
                         monotonic_set = true;
-                        if (sscanf(w+2, "%llx", &monotonic) != 1)
+                        if (sscanf(item+2, "%llx", &monotonic) != 1)
                                 k = -EINVAL;
                         break;
 
                 case 't':
                         realtime_set = true;
-                        if (sscanf(w+2, "%llx", &realtime) != 1)
+                        if (sscanf(item+2, "%llx", &realtime) != 1)
                                 k = -EINVAL;
                         break;
 
                 case 'x':
                         xor_hash_set = true;
-                        if (sscanf(w+2, "%llx", &xor_hash) != 1)
+                        if (sscanf(item+2, "%llx", &xor_hash) != 1)
                                 k = -EINVAL;
                         break;
                 }
@@ -1118,7 +1132,7 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
                 return 0;
         }
 
-        r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, NULL, &f);
+        r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
         free(path);
 
         if (r < 0) {
@@ -1242,9 +1256,10 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
         }
 
         for (;;) {
-                struct dirent buf, *de;
+                struct dirent *de;
+                union dirent_storage buf;
 
-                r = readdir_r(d, &buf, &de);
+                r = readdir_r(d, &buf.de, &de);
                 if (r != 0 || !de)
                         break;
 
@@ -1320,10 +1335,11 @@ static int add_root_directory(sd_journal *j, const char *p) {
         }
 
         for (;;) {
-                struct dirent buf, *de;
+                struct dirent *de;
+                union dirent_storage buf;
                 sd_id128_t id;
 
-                r = readdir_r(d, &buf, &de);
+                r = readdir_r(d, &buf.de, &de);
                 if (r != 0 || !de)
                         break;
 
@@ -1439,6 +1455,15 @@ static sd_journal *journal_new(int flags, const char *path) {
                 return NULL;
         }
 
+        j->mmap = mmap_cache_new();
+        if (!j->mmap) {
+                hashmap_free(j->files);
+                hashmap_free(j->directories_by_path);
+                free(j->path);
+                free(j);
+                return NULL;
+        }
+
         return j;
 }
 
@@ -1527,6 +1552,9 @@ _public_ void sd_journal_close(sd_journal *j) {
 
         sd_journal_flush_matches(j);
 
+        if (j->mmap)
+                mmap_cache_unref(j->mmap);
+
         free(j->path);
         free(j);
 }
@@ -2050,6 +2078,29 @@ void journal_print_header(sd_journal *j) {
         }
 }
 
+_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
+        Iterator i;
+        JournalFile *f;
+        uint64_t sum = 0;
+
+        if (!j)
+                return -EINVAL;
+        if (!bytes)
+                return -EINVAL;
+
+        HASHMAP_FOREACH(f, j->files, i) {
+                struct stat st;
+
+                if (fstat(f->fd, &st) < 0)
+                        return -errno;
+
+                sum += (uint64_t) st.st_blocks * 512ULL;
+        }
+
+        *bytes = sum;
+        return 0;
+}
+
 /* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */
 /*         if (!j) */
 /*                 return -EINVAL; */