chiark / gitweb /
0fefe2bc6e38ee03b879ad3cf4aeefa7c69bacc0
[elogind.git] / src / journal / sd-journal.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stddef.h>
25 #include <unistd.h>
26 #include <sys/inotify.h>
27 #include <sys/poll.h>
28 #include <sys/vfs.h>
29 #include <linux/magic.h>
30
31 #include "sd-journal.h"
32 #include "journal-def.h"
33 #include "journal-file.h"
34 #include "hashmap.h"
35 #include "list.h"
36 #include "strv.h"
37 #include "path-util.h"
38 #include "lookup3.h"
39 #include "compress.h"
40 #include "journal-internal.h"
41 #include "missing.h"
42 #include "catalog.h"
43 #include "replace-var.h"
44 #include "fileio.h"
45
46 #define JOURNAL_FILES_MAX 1024
47
48 #define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC)
49
50 #define REPLACE_VAR_MAX 256
51
52 #define DEFAULT_DATA_THRESHOLD (64*1024)
53
54 static void remove_file_real(sd_journal *j, JournalFile *f);
55
56 static bool journal_pid_changed(sd_journal *j) {
57         assert(j);
58
59         /* We don't support people creating a journal object and
60          * keeping it around over a fork(). Let's complain. */
61
62         return j->original_pid != getpid();
63 }
64
65 /* We return an error here only if we didn't manage to
66    memorize the real error. */
67 static int set_put_error(sd_journal *j, int r) {
68         int k;
69
70         if (r >= 0)
71                 return r;
72
73         k = set_ensure_allocated(&j->errors, NULL);
74         if (k < 0)
75                 return k;
76
77         return set_put(j->errors, INT_TO_PTR(r));
78 }
79
80 static void detach_location(sd_journal *j) {
81         Iterator i;
82         JournalFile *f;
83
84         assert(j);
85
86         j->current_file = NULL;
87         j->current_field = 0;
88
89         ORDERED_HASHMAP_FOREACH(f, j->files, i)
90                 journal_file_reset_location(f);
91 }
92
93 static void reset_location(sd_journal *j) {
94         assert(j);
95
96         detach_location(j);
97         zero(j->current_location);
98 }
99
100 static void init_location(Location *l, LocationType type, JournalFile *f, Object *o) {
101         assert(l);
102         assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
103         assert(f);
104         assert(o->object.type == OBJECT_ENTRY);
105
106         l->type = type;
107         l->seqnum = le64toh(o->entry.seqnum);
108         l->seqnum_id = f->header->seqnum_id;
109         l->realtime = le64toh(o->entry.realtime);
110         l->monotonic = le64toh(o->entry.monotonic);
111         l->boot_id = o->entry.boot_id;
112         l->xor_hash = le64toh(o->entry.xor_hash);
113
114         l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
115 }
116
117 static void set_location(sd_journal *j, JournalFile *f, Object *o) {
118         assert(j);
119         assert(f);
120         assert(o);
121
122         init_location(&j->current_location, LOCATION_DISCRETE, f, o);
123
124         j->current_file = f;
125         j->current_field = 0;
126
127         /* Let f know its candidate entry was picked. */
128         assert(f->location_type == LOCATION_SEEK);
129         f->location_type = LOCATION_DISCRETE;
130 }
131
132 static int match_is_valid(const void *data, size_t size) {
133         const char *b, *p;
134
135         assert(data);
136
137         if (size < 2)
138                 return false;
139
140         if (startswith(data, "__"))
141                 return false;
142
143         b = data;
144         for (p = b; p < b + size; p++) {
145
146                 if (*p == '=')
147                         return p > b;
148
149                 if (*p == '_')
150                         continue;
151
152                 if (*p >= 'A' && *p <= 'Z')
153                         continue;
154
155                 if (*p >= '0' && *p <= '9')
156                         continue;
157
158                 return false;
159         }
160
161         return false;
162 }
163
164 static bool same_field(const void *_a, size_t s, const void *_b, size_t t) {
165         const uint8_t *a = _a, *b = _b;
166         size_t j;
167
168         for (j = 0; j < s && j < t; j++) {
169
170                 if (a[j] != b[j])
171                         return false;
172
173                 if (a[j] == '=')
174                         return true;
175         }
176
177         assert_not_reached("\"=\" not found");
178 }
179
180 static Match *match_new(Match *p, MatchType t) {
181         Match *m;
182
183         m = new0(Match, 1);
184         if (!m)
185                 return NULL;
186
187         m->type = t;
188
189         if (p) {
190                 m->parent = p;
191                 LIST_PREPEND(matches, p->matches, m);
192         }
193
194         return m;
195 }
196
197 static void match_free(Match *m) {
198         assert(m);
199
200         while (m->matches)
201                 match_free(m->matches);
202
203         if (m->parent)
204                 LIST_REMOVE(matches, m->parent->matches, m);
205
206         free(m->data);
207         free(m);
208 }
209
210 static void match_free_if_empty(Match *m) {
211         if (!m || m->matches)
212                 return;
213
214         match_free(m);
215 }
216
217 _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) {
218         Match *l3, *l4, *add_here = NULL, *m;
219         le64_t le_hash;
220
221         assert_return(j, -EINVAL);
222         assert_return(!journal_pid_changed(j), -ECHILD);
223         assert_return(data, -EINVAL);
224
225         if (size == 0)
226                 size = strlen(data);
227
228         assert_return(match_is_valid(data, size), -EINVAL);
229
230         /* level 0: AND term
231          * level 1: OR terms
232          * level 2: AND terms
233          * level 3: OR terms
234          * level 4: concrete matches */
235
236         if (!j->level0) {
237                 j->level0 = match_new(NULL, MATCH_AND_TERM);
238                 if (!j->level0)
239                         return -ENOMEM;
240         }
241
242         if (!j->level1) {
243                 j->level1 = match_new(j->level0, MATCH_OR_TERM);
244                 if (!j->level1)
245                         return -ENOMEM;
246         }
247
248         if (!j->level2) {
249                 j->level2 = match_new(j->level1, MATCH_AND_TERM);
250                 if (!j->level2)
251                         return -ENOMEM;
252         }
253
254         assert(j->level0->type == MATCH_AND_TERM);
255         assert(j->level1->type == MATCH_OR_TERM);
256         assert(j->level2->type == MATCH_AND_TERM);
257
258         le_hash = htole64(hash64(data, size));
259
260         LIST_FOREACH(matches, l3, j->level2->matches) {
261                 assert(l3->type == MATCH_OR_TERM);
262
263                 LIST_FOREACH(matches, l4, l3->matches) {
264                         assert(l4->type == MATCH_DISCRETE);
265
266                         /* Exactly the same match already? Then ignore
267                          * this addition */
268                         if (l4->le_hash == le_hash &&
269                             l4->size == size &&
270                             memcmp(l4->data, data, size) == 0)
271                                 return 0;
272
273                         /* Same field? Then let's add this to this OR term */
274                         if (same_field(data, size, l4->data, l4->size)) {
275                                 add_here = l3;
276                                 break;
277                         }
278                 }
279
280                 if (add_here)
281                         break;
282         }
283
284         if (!add_here) {
285                 add_here = match_new(j->level2, MATCH_OR_TERM);
286                 if (!add_here)
287                         goto fail;
288         }
289
290         m = match_new(add_here, MATCH_DISCRETE);
291         if (!m)
292                 goto fail;
293
294         m->le_hash = le_hash;
295         m->size = size;
296         m->data = memdup(data, size);
297         if (!m->data)
298                 goto fail;
299
300         detach_location(j);
301
302         return 0;
303
304 fail:
305         match_free_if_empty(add_here);
306         match_free_if_empty(j->level2);
307         match_free_if_empty(j->level1);
308         match_free_if_empty(j->level0);
309
310         return -ENOMEM;
311 }
312
313 _public_ int sd_journal_add_conjunction(sd_journal *j) {
314         assert_return(j, -EINVAL);
315         assert_return(!journal_pid_changed(j), -ECHILD);
316
317         if (!j->level0)
318                 return 0;
319
320         if (!j->level1)
321                 return 0;
322
323         if (!j->level1->matches)
324                 return 0;
325
326         j->level1 = NULL;
327         j->level2 = NULL;
328
329         return 0;
330 }
331
332 _public_ int sd_journal_add_disjunction(sd_journal *j) {
333         assert_return(j, -EINVAL);
334         assert_return(!journal_pid_changed(j), -ECHILD);
335
336         if (!j->level0)
337                 return 0;
338
339         if (!j->level1)
340                 return 0;
341
342         if (!j->level2)
343                 return 0;
344
345         if (!j->level2->matches)
346                 return 0;
347
348         j->level2 = NULL;
349         return 0;
350 }
351
352 static char *match_make_string(Match *m) {
353         char *p, *r;
354         Match *i;
355         bool enclose = false;
356
357         if (!m)
358                 return strdup("none");
359
360         if (m->type == MATCH_DISCRETE)
361                 return strndup(m->data, m->size);
362
363         p = NULL;
364         LIST_FOREACH(matches, i, m->matches) {
365                 char *t, *k;
366
367                 t = match_make_string(i);
368                 if (!t) {
369                         free(p);
370                         return NULL;
371                 }
372
373                 if (p) {
374                         k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL);
375                         free(p);
376                         free(t);
377
378                         if (!k)
379                                 return NULL;
380
381                         p = k;
382
383                         enclose = true;
384                 } else
385                         p = t;
386         }
387
388         if (enclose) {
389                 r = strjoin("(", p, ")", NULL);
390                 free(p);
391                 return r;
392         }
393
394         return p;
395 }
396
397 char *journal_make_match_string(sd_journal *j) {
398         assert(j);
399
400         return match_make_string(j->level0);
401 }
402
403 _public_ void sd_journal_flush_matches(sd_journal *j) {
404         if (!j)
405                 return;
406
407         if (j->level0)
408                 match_free(j->level0);
409
410         j->level0 = j->level1 = j->level2 = NULL;
411
412         detach_location(j);
413 }
414
415 _pure_ static int compare_with_location(JournalFile *af, Object *ao, Location *l) {
416         uint64_t a;
417
418         assert(af);
419         assert(ao);
420         assert(l);
421         assert(l->type == LOCATION_DISCRETE || l->type == LOCATION_SEEK);
422
423         if (l->monotonic_set &&
424             sd_id128_equal(ao->entry.boot_id, l->boot_id) &&
425             l->realtime_set &&
426             le64toh(ao->entry.realtime) == l->realtime &&
427             l->xor_hash_set &&
428             le64toh(ao->entry.xor_hash) == l->xor_hash)
429                 return 0;
430
431         if (l->seqnum_set &&
432             sd_id128_equal(af->header->seqnum_id, l->seqnum_id)) {
433
434                 a = le64toh(ao->entry.seqnum);
435
436                 if (a < l->seqnum)
437                         return -1;
438                 if (a > l->seqnum)
439                         return 1;
440         }
441
442         if (l->monotonic_set &&
443             sd_id128_equal(ao->entry.boot_id, l->boot_id)) {
444
445                 a = le64toh(ao->entry.monotonic);
446
447                 if (a < l->monotonic)
448                         return -1;
449                 if (a > l->monotonic)
450                         return 1;
451         }
452
453         if (l->realtime_set) {
454
455                 a = le64toh(ao->entry.realtime);
456
457                 if (a < l->realtime)
458                         return -1;
459                 if (a > l->realtime)
460                         return 1;
461         }
462
463         if (l->xor_hash_set) {
464                 a = le64toh(ao->entry.xor_hash);
465
466                 if (a < l->xor_hash)
467                         return -1;
468                 if (a > l->xor_hash)
469                         return 1;
470         }
471
472         return 0;
473 }
474
475 static int next_for_match(
476                 sd_journal *j,
477                 Match *m,
478                 JournalFile *f,
479                 uint64_t after_offset,
480                 direction_t direction,
481                 Object **ret,
482                 uint64_t *offset) {
483
484         int r;
485         uint64_t np = 0;
486         Object *n;
487
488         assert(j);
489         assert(m);
490         assert(f);
491
492         if (m->type == MATCH_DISCRETE) {
493                 uint64_t dp;
494
495                 r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
496                 if (r <= 0)
497                         return r;
498
499                 return journal_file_move_to_entry_by_offset_for_data(f, dp, after_offset, direction, ret, offset);
500
501         } else if (m->type == MATCH_OR_TERM) {
502                 Match *i;
503
504                 /* Find the earliest match beyond after_offset */
505
506                 LIST_FOREACH(matches, i, m->matches) {
507                         uint64_t cp;
508
509                         r = next_for_match(j, i, f, after_offset, direction, NULL, &cp);
510                         if (r < 0)
511                                 return r;
512                         else if (r > 0) {
513                                 if (np == 0 || (direction == DIRECTION_DOWN ? cp < np : cp > np))
514                                         np = cp;
515                         }
516                 }
517
518                 if (np == 0)
519                         return 0;
520
521         } else if (m->type == MATCH_AND_TERM) {
522                 Match *i, *last_moved;
523
524                 /* Always jump to the next matching entry and repeat
525                  * this until we find an offset that matches for all
526                  * matches. */
527
528                 if (!m->matches)
529                         return 0;
530
531                 r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np);
532                 if (r <= 0)
533                         return r;
534
535                 assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset);
536                 last_moved = m->matches;
537
538                 LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) {
539                         uint64_t cp;
540
541                         r = next_for_match(j, i, f, np, direction, NULL, &cp);
542                         if (r <= 0)
543                                 return r;
544
545                         assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np);
546                         if (direction == DIRECTION_DOWN ? cp > np : cp < np) {
547                                 np = cp;
548                                 last_moved = i;
549                         }
550                 }
551         }
552
553         assert(np > 0);
554
555         r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
556         if (r < 0)
557                 return r;
558
559         if (ret)
560                 *ret = n;
561         if (offset)
562                 *offset = np;
563
564         return 1;
565 }
566
567 static int find_location_for_match(
568                 sd_journal *j,
569                 Match *m,
570                 JournalFile *f,
571                 direction_t direction,
572                 Object **ret,
573                 uint64_t *offset) {
574
575         int r;
576
577         assert(j);
578         assert(m);
579         assert(f);
580
581         if (m->type == MATCH_DISCRETE) {
582                 uint64_t dp;
583
584                 r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
585                 if (r <= 0)
586                         return r;
587
588                 /* FIXME: missing: find by monotonic */
589
590                 if (j->current_location.type == LOCATION_HEAD)
591                         return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset);
592                 if (j->current_location.type == LOCATION_TAIL)
593                         return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset);
594                 if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
595                         return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset);
596                 if (j->current_location.monotonic_set) {
597                         r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
598                         if (r != -ENOENT)
599                                 return r;
600                 }
601                 if (j->current_location.realtime_set)
602                         return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset);
603
604                 return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset);
605
606         } else if (m->type == MATCH_OR_TERM) {
607                 uint64_t np = 0;
608                 Object *n;
609                 Match *i;
610
611                 /* Find the earliest match */
612
613                 LIST_FOREACH(matches, i, m->matches) {
614                         uint64_t cp;
615
616                         r = find_location_for_match(j, i, f, direction, NULL, &cp);
617                         if (r < 0)
618                                 return r;
619                         else if (r > 0) {
620                                 if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
621                                         np = cp;
622                         }
623                 }
624
625                 if (np == 0)
626                         return 0;
627
628                 r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
629                 if (r < 0)
630                         return r;
631
632                 if (ret)
633                         *ret = n;
634                 if (offset)
635                         *offset = np;
636
637                 return 1;
638
639         } else {
640                 Match *i;
641                 uint64_t np = 0;
642
643                 assert(m->type == MATCH_AND_TERM);
644
645                 /* First jump to the last match, and then find the
646                  * next one where all matches match */
647
648                 if (!m->matches)
649                         return 0;
650
651                 LIST_FOREACH(matches, i, m->matches) {
652                         uint64_t cp;
653
654                         r = find_location_for_match(j, i, f, direction, NULL, &cp);
655                         if (r <= 0)
656                                 return r;
657
658                         if (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))
659                                 np = cp;
660                 }
661
662                 return next_for_match(j, m, f, np, direction, ret, offset);
663         }
664 }
665
666 static int find_location_with_matches(
667                 sd_journal *j,
668                 JournalFile *f,
669                 direction_t direction,
670                 Object **ret,
671                 uint64_t *offset) {
672
673         int r;
674
675         assert(j);
676         assert(f);
677         assert(ret);
678         assert(offset);
679
680         if (!j->level0) {
681                 /* No matches is simple */
682
683                 if (j->current_location.type == LOCATION_HEAD)
684                         return journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, ret, offset);
685                 if (j->current_location.type == LOCATION_TAIL)
686                         return journal_file_next_entry(f, NULL, 0, DIRECTION_UP, ret, offset);
687                 if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
688                         return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
689                 if (j->current_location.monotonic_set) {
690                         r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
691                         if (r != -ENOENT)
692                                 return r;
693                 }
694                 if (j->current_location.realtime_set)
695                         return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
696
697                 return journal_file_next_entry(f, NULL, 0, direction, ret, offset);
698         } else
699                 return find_location_for_match(j, j->level0, f, direction, ret, offset);
700 }
701
702 static int next_with_matches(
703                 sd_journal *j,
704                 JournalFile *f,
705                 direction_t direction,
706                 Object **ret,
707                 uint64_t *offset) {
708
709         Object *c;
710         uint64_t cp;
711
712         assert(j);
713         assert(f);
714         assert(ret);
715         assert(offset);
716
717         c = *ret;
718         cp = *offset;
719
720         /* No matches is easy. We simple advance the file
721          * pointer by one. */
722         if (!j->level0)
723                 return journal_file_next_entry(f, c, cp, direction, ret, offset);
724
725         /* If we have a match then we look for the next matching entry
726          * with an offset at least one step larger */
727         return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? cp+1 : cp-1, direction, ret, offset);
728 }
729
730 static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction) {
731         Object *c;
732         uint64_t cp, n_entries;
733         int r;
734
735         assert(j);
736         assert(f);
737
738         /* If we hit EOF before, recheck if any new entries arrived. */
739         n_entries = le64toh(f->header->n_entries);
740         if (f->location_type == LOCATION_TAIL && n_entries == f->last_n_entries)
741                 return 0;
742         f->last_n_entries = n_entries;
743
744         if (f->last_direction == direction && f->current_offset > 0) {
745                 /* LOCATION_SEEK here means we did the work in a previous
746                  * iteration and the current location already points to a
747                  * candidate entry. */
748                 if (f->location_type == LOCATION_SEEK)
749                         return 1;
750
751                 cp = f->current_offset;
752
753                 r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
754                 if (r < 0)
755                         return r;
756
757                 r = next_with_matches(j, f, direction, &c, &cp);
758                 if (r <= 0)
759                         return r;
760         } else {
761                 r = find_location_with_matches(j, f, direction, &c, &cp);
762                 if (r <= 0)
763                         return r;
764         }
765
766         /* OK, we found the spot, now let's advance until an entry
767          * that is actually different from what we were previously
768          * looking at. This is necessary to handle entries which exist
769          * in two (or more) journal files, and which shall all be
770          * suppressed but one. */
771
772         for (;;) {
773                 bool found;
774
775                 if (j->current_location.type == LOCATION_DISCRETE) {
776                         int k;
777
778                         k = compare_with_location(f, c, &j->current_location);
779
780                         found = direction == DIRECTION_DOWN ? k > 0 : k < 0;
781                 } else
782                         found = true;
783
784                 if (found) {
785                         journal_file_save_location(f, direction, c, cp);
786                         return 1;
787                 }
788
789                 r = next_with_matches(j, f, direction, &c, &cp);
790                 if (r <= 0)
791                         return r;
792         }
793 }
794
795 static int real_journal_next(sd_journal *j, direction_t direction) {
796         JournalFile *f, *new_file = NULL;
797         Iterator i;
798         Object *o;
799         int r;
800
801         assert_return(j, -EINVAL);
802         assert_return(!journal_pid_changed(j), -ECHILD);
803
804         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
805                 bool found;
806
807                 r = next_beyond_location(j, f, direction);
808                 if (r < 0) {
809                         log_debug_errno(r, "Can't iterate through %s, ignoring: %m", f->path);
810                         remove_file_real(j, f);
811                         continue;
812                 } else if (r == 0) {
813                         f->location_type = LOCATION_TAIL;
814                         continue;
815                 }
816
817                 if (!new_file)
818                         found = true;
819                 else {
820                         int k;
821
822                         k = journal_file_compare_locations(f, new_file);
823
824                         found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
825                 }
826
827                 if (found)
828                         new_file = f;
829         }
830
831         if (!new_file)
832                 return 0;
833
834         r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_file->current_offset, &o);
835         if (r < 0)
836                 return r;
837
838         set_location(j, new_file, o);
839
840         return 1;
841 }
842
843 _public_ int sd_journal_next(sd_journal *j) {
844         return real_journal_next(j, DIRECTION_DOWN);
845 }
846
847 _public_ int sd_journal_previous(sd_journal *j) {
848         return real_journal_next(j, DIRECTION_UP);
849 }
850
851 static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) {
852         int c = 0, r;
853
854         assert_return(j, -EINVAL);
855         assert_return(!journal_pid_changed(j), -ECHILD);
856
857         if (skip == 0) {
858                 /* If this is not a discrete skip, then at least
859                  * resolve the current location */
860                 if (j->current_location.type != LOCATION_DISCRETE)
861                         return real_journal_next(j, direction);
862
863                 return 0;
864         }
865
866         do {
867                 r = real_journal_next(j, direction);
868                 if (r < 0)
869                         return r;
870
871                 if (r == 0)
872                         return c;
873
874                 skip--;
875                 c++;
876         } while (skip > 0);
877
878         return c;
879 }
880
881 _public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) {
882         return real_journal_next_skip(j, DIRECTION_DOWN, skip);
883 }
884
885 _public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) {
886         return real_journal_next_skip(j, DIRECTION_UP, skip);
887 }
888
889 _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
890         Object *o;
891         int r;
892         char bid[33], sid[33];
893
894         assert_return(j, -EINVAL);
895         assert_return(!journal_pid_changed(j), -ECHILD);
896         assert_return(cursor, -EINVAL);
897
898         if (!j->current_file || j->current_file->current_offset <= 0)
899                 return -EADDRNOTAVAIL;
900
901         r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
902         if (r < 0)
903                 return r;
904
905         sd_id128_to_string(j->current_file->header->seqnum_id, sid);
906         sd_id128_to_string(o->entry.boot_id, bid);
907
908         if (asprintf(cursor,
909                      "s=%s;i=%"PRIx64";b=%s;m=%"PRIx64";t=%"PRIx64";x=%"PRIx64,
910                      sid, le64toh(o->entry.seqnum),
911                      bid, le64toh(o->entry.monotonic),
912                      le64toh(o->entry.realtime),
913                      le64toh(o->entry.xor_hash)) < 0)
914                 return -ENOMEM;
915
916         return 0;
917 }
918
919 _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
920         const char *word, *state;
921         size_t l;
922         unsigned long long seqnum, monotonic, realtime, xor_hash;
923         bool
924                 seqnum_id_set = false,
925                 seqnum_set = false,
926                 boot_id_set = false,
927                 monotonic_set = false,
928                 realtime_set = false,
929                 xor_hash_set = false;
930         sd_id128_t seqnum_id, boot_id;
931
932         assert_return(j, -EINVAL);
933         assert_return(!journal_pid_changed(j), -ECHILD);
934         assert_return(!isempty(cursor), -EINVAL);
935
936         FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
937                 char *item;
938                 int k = 0;
939
940                 if (l < 2 || word[1] != '=')
941                         return -EINVAL;
942
943                 item = strndup(word, l);
944                 if (!item)
945                         return -ENOMEM;
946
947                 switch (word[0]) {
948
949                 case 's':
950                         seqnum_id_set = true;
951                         k = sd_id128_from_string(item+2, &seqnum_id);
952                         break;
953
954                 case 'i':
955                         seqnum_set = true;
956                         if (sscanf(item+2, "%llx", &seqnum) != 1)
957                                 k = -EINVAL;
958                         break;
959
960                 case 'b':
961                         boot_id_set = true;
962                         k = sd_id128_from_string(item+2, &boot_id);
963                         break;
964
965                 case 'm':
966                         monotonic_set = true;
967                         if (sscanf(item+2, "%llx", &monotonic) != 1)
968                                 k = -EINVAL;
969                         break;
970
971                 case 't':
972                         realtime_set = true;
973                         if (sscanf(item+2, "%llx", &realtime) != 1)
974                                 k = -EINVAL;
975                         break;
976
977                 case 'x':
978                         xor_hash_set = true;
979                         if (sscanf(item+2, "%llx", &xor_hash) != 1)
980                                 k = -EINVAL;
981                         break;
982                 }
983
984                 free(item);
985
986                 if (k < 0)
987                         return k;
988         }
989
990         if ((!seqnum_set || !seqnum_id_set) &&
991             (!monotonic_set || !boot_id_set) &&
992             !realtime_set)
993                 return -EINVAL;
994
995         reset_location(j);
996
997         j->current_location.type = LOCATION_SEEK;
998
999         if (realtime_set) {
1000                 j->current_location.realtime = (uint64_t) realtime;
1001                 j->current_location.realtime_set = true;
1002         }
1003
1004         if (seqnum_set && seqnum_id_set) {
1005                 j->current_location.seqnum = (uint64_t) seqnum;
1006                 j->current_location.seqnum_id = seqnum_id;
1007                 j->current_location.seqnum_set = true;
1008         }
1009
1010         if (monotonic_set && boot_id_set) {
1011                 j->current_location.monotonic = (uint64_t) monotonic;
1012                 j->current_location.boot_id = boot_id;
1013                 j->current_location.monotonic_set = true;
1014         }
1015
1016         if (xor_hash_set) {
1017                 j->current_location.xor_hash = (uint64_t) xor_hash;
1018                 j->current_location.xor_hash_set = true;
1019         }
1020
1021         return 0;
1022 }
1023
1024 _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
1025         int r;
1026         const char *word, *state;
1027         size_t l;
1028         Object *o;
1029
1030         assert_return(j, -EINVAL);
1031         assert_return(!journal_pid_changed(j), -ECHILD);
1032         assert_return(!isempty(cursor), -EINVAL);
1033
1034         if (!j->current_file || j->current_file->current_offset <= 0)
1035                 return -EADDRNOTAVAIL;
1036
1037         r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
1038         if (r < 0)
1039                 return r;
1040
1041         FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
1042                 _cleanup_free_ char *item = NULL;
1043                 sd_id128_t id;
1044                 unsigned long long ll;
1045                 int k = 0;
1046
1047                 if (l < 2 || word[1] != '=')
1048                         return -EINVAL;
1049
1050                 item = strndup(word, l);
1051                 if (!item)
1052                         return -ENOMEM;
1053
1054                 switch (word[0]) {
1055
1056                 case 's':
1057                         k = sd_id128_from_string(item+2, &id);
1058                         if (k < 0)
1059                                 return k;
1060                         if (!sd_id128_equal(id, j->current_file->header->seqnum_id))
1061                                 return 0;
1062                         break;
1063
1064                 case 'i':
1065                         if (sscanf(item+2, "%llx", &ll) != 1)
1066                                 return -EINVAL;
1067                         if (ll != le64toh(o->entry.seqnum))
1068                                 return 0;
1069                         break;
1070
1071                 case 'b':
1072                         k = sd_id128_from_string(item+2, &id);
1073                         if (k < 0)
1074                                 return k;
1075                         if (!sd_id128_equal(id, o->entry.boot_id))
1076                                 return 0;
1077                         break;
1078
1079                 case 'm':
1080                         if (sscanf(item+2, "%llx", &ll) != 1)
1081                                 return -EINVAL;
1082                         if (ll != le64toh(o->entry.monotonic))
1083                                 return 0;
1084                         break;
1085
1086                 case 't':
1087                         if (sscanf(item+2, "%llx", &ll) != 1)
1088                                 return -EINVAL;
1089                         if (ll != le64toh(o->entry.realtime))
1090                                 return 0;
1091                         break;
1092
1093                 case 'x':
1094                         if (sscanf(item+2, "%llx", &ll) != 1)
1095                                 return -EINVAL;
1096                         if (ll != le64toh(o->entry.xor_hash))
1097                                 return 0;
1098                         break;
1099                 }
1100         }
1101
1102         return 1;
1103 }
1104
1105
1106 _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
1107         assert_return(j, -EINVAL);
1108         assert_return(!journal_pid_changed(j), -ECHILD);
1109
1110         reset_location(j);
1111         j->current_location.type = LOCATION_SEEK;
1112         j->current_location.boot_id = boot_id;
1113         j->current_location.monotonic = usec;
1114         j->current_location.monotonic_set = true;
1115
1116         return 0;
1117 }
1118
1119 _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
1120         assert_return(j, -EINVAL);
1121         assert_return(!journal_pid_changed(j), -ECHILD);
1122
1123         reset_location(j);
1124         j->current_location.type = LOCATION_SEEK;
1125         j->current_location.realtime = usec;
1126         j->current_location.realtime_set = true;
1127
1128         return 0;
1129 }
1130
1131 _public_ int sd_journal_seek_head(sd_journal *j) {
1132         assert_return(j, -EINVAL);
1133         assert_return(!journal_pid_changed(j), -ECHILD);
1134
1135         reset_location(j);
1136         j->current_location.type = LOCATION_HEAD;
1137
1138         return 0;
1139 }
1140
1141 _public_ int sd_journal_seek_tail(sd_journal *j) {
1142         assert_return(j, -EINVAL);
1143         assert_return(!journal_pid_changed(j), -ECHILD);
1144
1145         reset_location(j);
1146         j->current_location.type = LOCATION_TAIL;
1147
1148         return 0;
1149 }
1150
1151 static void check_network(sd_journal *j, int fd) {
1152         struct statfs sfs;
1153
1154         assert(j);
1155
1156         if (j->on_network)
1157                 return;
1158
1159         if (fstatfs(fd, &sfs) < 0)
1160                 return;
1161
1162         j->on_network =
1163                 F_TYPE_EQUAL(sfs.f_type, CIFS_MAGIC_NUMBER) ||
1164                 F_TYPE_EQUAL(sfs.f_type, CODA_SUPER_MAGIC) ||
1165                 F_TYPE_EQUAL(sfs.f_type, NCP_SUPER_MAGIC) ||
1166                 F_TYPE_EQUAL(sfs.f_type, NFS_SUPER_MAGIC) ||
1167                 F_TYPE_EQUAL(sfs.f_type, SMB_SUPER_MAGIC);
1168 }
1169
1170 static bool file_has_type_prefix(const char *prefix, const char *filename) {
1171         const char *full, *tilded, *atted;
1172
1173         full = strappenda(prefix, ".journal");
1174         tilded = strappenda(full, "~");
1175         atted = strappenda(prefix, "@");
1176
1177         return streq(filename, full) ||
1178                streq(filename, tilded) ||
1179                startswith(filename, atted);
1180 }
1181
1182 static bool file_type_wanted(int flags, const char *filename) {
1183         if (!endswith(filename, ".journal") && !endswith(filename, ".journal~"))
1184                 return false;
1185
1186         /* no flags set â†’ every type is OK */
1187         if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)))
1188                 return true;
1189
1190         if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename))
1191                 return true;
1192
1193         if (flags & SD_JOURNAL_CURRENT_USER) {
1194                 char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1];
1195
1196                 assert_se(snprintf(prefix, sizeof(prefix), "user-"UID_FMT, getuid())
1197                           < (int) sizeof(prefix));
1198
1199                 if (file_has_type_prefix(prefix, filename))
1200                         return true;
1201         }
1202
1203         return false;
1204 }
1205
1206 static int add_any_file(sd_journal *j, const char *path) {
1207         JournalFile *f = NULL;
1208         int r;
1209
1210         assert(j);
1211         assert(path);
1212
1213         if (ordered_hashmap_get(j->files, path))
1214                 return 0;
1215
1216         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
1217                 log_warning("Too many open journal files, not adding %s.", path);
1218                 return set_put_error(j, -ETOOMANYREFS);
1219         }
1220
1221         r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
1222         if (r < 0)
1223                 return r;
1224
1225         /* journal_file_dump(f); */
1226
1227         r = ordered_hashmap_put(j->files, f->path, f);
1228         if (r < 0) {
1229                 journal_file_close(f);
1230                 return r;
1231         }
1232
1233         log_debug("File %s added.", f->path);
1234
1235         check_network(j, f->fd);
1236
1237         j->current_invalidate_counter ++;
1238
1239         return 0;
1240 }
1241
1242 static int add_file(sd_journal *j, const char *prefix, const char *filename) {
1243         _cleanup_free_ char *path = NULL;
1244         int r;
1245
1246         assert(j);
1247         assert(prefix);
1248         assert(filename);
1249
1250         if (j->no_new_files ||
1251             !file_type_wanted(j->flags, filename))
1252                 return 0;
1253
1254         path = strjoin(prefix, "/", filename, NULL);
1255         if (!path)
1256                 return -ENOMEM;
1257
1258         r = add_any_file(j, path);
1259         if (r == -ENOENT)
1260                 return 0;
1261         return 0;
1262 }
1263
1264 static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
1265         _cleanup_free_ char *path;
1266         JournalFile *f;
1267
1268         assert(j);
1269         assert(prefix);
1270         assert(filename);
1271
1272         path = strjoin(prefix, "/", filename, NULL);
1273         if (!path)
1274                 return -ENOMEM;
1275
1276         f = ordered_hashmap_get(j->files, path);
1277         if (!f)
1278                 return 0;
1279
1280         remove_file_real(j, f);
1281         return 0;
1282 }
1283
1284 static void remove_file_real(sd_journal *j, JournalFile *f) {
1285         assert(j);
1286         assert(f);
1287
1288         ordered_hashmap_remove(j->files, f->path);
1289
1290         log_debug("File %s removed.", f->path);
1291
1292         if (j->current_file == f) {
1293                 j->current_file = NULL;
1294                 j->current_field = 0;
1295         }
1296
1297         if (j->unique_file == f) {
1298                 /* Jump to the next unique_file or NULL if that one was last */
1299                 j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
1300                 j->unique_offset = 0;
1301                 if (!j->unique_file)
1302                         j->unique_file_lost = true;
1303         }
1304
1305         journal_file_close(f);
1306
1307         j->current_invalidate_counter ++;
1308 }
1309
1310 static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
1311         _cleanup_free_ char *path = NULL;
1312         int r;
1313         _cleanup_closedir_ DIR *d = NULL;
1314         sd_id128_t id, mid;
1315         Directory *m;
1316
1317         assert(j);
1318         assert(prefix);
1319         assert(dirname);
1320
1321         log_debug("Considering %s/%s.", prefix, dirname);
1322
1323         if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
1324             (sd_id128_from_string(dirname, &id) < 0 ||
1325              sd_id128_get_machine(&mid) < 0 ||
1326              !(sd_id128_equal(id, mid) || path_startswith(prefix, "/run"))))
1327             return 0;
1328
1329         path = strjoin(prefix, "/", dirname, NULL);
1330         if (!path)
1331                 return -ENOMEM;
1332
1333         d = opendir(path);
1334         if (!d) {
1335                 log_debug_errno(errno, "Failed to open %s: %m", path);
1336                 if (errno == ENOENT)
1337                         return 0;
1338                 return -errno;
1339         }
1340
1341         m = hashmap_get(j->directories_by_path, path);
1342         if (!m) {
1343                 m = new0(Directory, 1);
1344                 if (!m)
1345                         return -ENOMEM;
1346
1347                 m->is_root = false;
1348                 m->path = path;
1349
1350                 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1351                         free(m);
1352                         return -ENOMEM;
1353                 }
1354
1355                 path = NULL; /* avoid freeing in cleanup */
1356                 j->current_invalidate_counter ++;
1357
1358                 log_debug("Directory %s added.", m->path);
1359
1360         } else if (m->is_root)
1361                 return 0;
1362
1363         if (m->wd <= 0 && j->inotify_fd >= 0) {
1364
1365                 m->wd = inotify_add_watch(j->inotify_fd, m->path,
1366                                           IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
1367                                           IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
1368                                           IN_ONLYDIR);
1369
1370                 if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
1371                         inotify_rm_watch(j->inotify_fd, m->wd);
1372         }
1373
1374         for (;;) {
1375                 struct dirent *de;
1376
1377                 errno = 0;
1378                 de = readdir(d);
1379                 if (!de && errno != 0) {
1380                         r = -errno;
1381                         log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
1382                         return r;
1383                 }
1384                 if (!de)
1385                         break;
1386
1387                 if (dirent_is_file_with_suffix(de, ".journal") ||
1388                     dirent_is_file_with_suffix(de, ".journal~")) {
1389                         r = add_file(j, m->path, de->d_name);
1390                         if (r < 0) {
1391                                 log_debug_errno(r, "Failed to add file %s/%s: %m",
1392                                                 m->path, de->d_name);
1393                                 r = set_put_error(j, r);
1394                                 if (r < 0)
1395                                         return r;
1396                         }
1397                 }
1398         }
1399
1400         check_network(j, dirfd(d));
1401
1402         return 0;
1403 }
1404
1405 static int add_root_directory(sd_journal *j, const char *p) {
1406         _cleanup_closedir_ DIR *d = NULL;
1407         Directory *m;
1408         int r;
1409
1410         assert(j);
1411         assert(p);
1412
1413         if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
1414             !path_startswith(p, "/run"))
1415                 return -EINVAL;
1416
1417         if (j->prefix)
1418                 p = strappenda(j->prefix, p);
1419
1420         d = opendir(p);
1421         if (!d)
1422                 return -errno;
1423
1424         m = hashmap_get(j->directories_by_path, p);
1425         if (!m) {
1426                 m = new0(Directory, 1);
1427                 if (!m)
1428                         return -ENOMEM;
1429
1430                 m->is_root = true;
1431                 m->path = strdup(p);
1432                 if (!m->path) {
1433                         free(m);
1434                         return -ENOMEM;
1435                 }
1436
1437                 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1438                         free(m->path);
1439                         free(m);
1440                         return -ENOMEM;
1441                 }
1442
1443                 j->current_invalidate_counter ++;
1444
1445                 log_debug("Root directory %s added.", m->path);
1446
1447         } else if (!m->is_root)
1448                 return 0;
1449
1450         if (m->wd <= 0 && j->inotify_fd >= 0) {
1451
1452                 m->wd = inotify_add_watch(j->inotify_fd, m->path,
1453                                           IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
1454                                           IN_ONLYDIR);
1455
1456                 if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
1457                         inotify_rm_watch(j->inotify_fd, m->wd);
1458         }
1459
1460         if (j->no_new_files)
1461                 return 0;
1462
1463         for (;;) {
1464                 struct dirent *de;
1465                 sd_id128_t id;
1466
1467                 errno = 0;
1468                 de = readdir(d);
1469                 if (!de && errno != 0) {
1470                         r = -errno;
1471                         log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
1472                         return r;
1473                 }
1474                 if (!de)
1475                         break;
1476
1477                 if (dirent_is_file_with_suffix(de, ".journal") ||
1478                     dirent_is_file_with_suffix(de, ".journal~")) {
1479                         r = add_file(j, m->path, de->d_name);
1480                         if (r < 0) {
1481                                 log_debug_errno(r, "Failed to add file %s/%s: %m",
1482                                                 m->path, de->d_name);
1483                                 r = set_put_error(j, r);
1484                                 if (r < 0)
1485                                         return r;
1486                         }
1487                 } else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
1488                            sd_id128_from_string(de->d_name, &id) >= 0) {
1489
1490                         r = add_directory(j, m->path, de->d_name);
1491                         if (r < 0)
1492                                 log_debug_errno(r, "Failed to add directory %s/%s: %m", m->path, de->d_name);
1493                 }
1494         }
1495
1496         check_network(j, dirfd(d));
1497
1498         return 0;
1499 }
1500
1501 static int remove_directory(sd_journal *j, Directory *d) {
1502         assert(j);
1503
1504         if (d->wd > 0) {
1505                 hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd));
1506
1507                 if (j->inotify_fd >= 0)
1508                         inotify_rm_watch(j->inotify_fd, d->wd);
1509         }
1510
1511         hashmap_remove(j->directories_by_path, d->path);
1512
1513         if (d->is_root)
1514                 log_debug("Root directory %s removed.", d->path);
1515         else
1516                 log_debug("Directory %s removed.", d->path);
1517
1518         free(d->path);
1519         free(d);
1520
1521         return 0;
1522 }
1523
1524 static int add_search_paths(sd_journal *j) {
1525         int r;
1526         const char search_paths[] =
1527                 "/run/log/journal\0"
1528                 "/var/log/journal\0";
1529         const char *p;
1530
1531         assert(j);
1532
1533         /* We ignore most errors here, since the idea is to only open
1534          * what's actually accessible, and ignore the rest. */
1535
1536         NULSTR_FOREACH(p, search_paths) {
1537                 r = add_root_directory(j, p);
1538                 if (r < 0 && r != -ENOENT) {
1539                         r = set_put_error(j, r);
1540                         if (r < 0)
1541                                 return r;
1542                 }
1543         }
1544
1545         return 0;
1546 }
1547
1548 static int add_current_paths(sd_journal *j) {
1549         Iterator i;
1550         JournalFile *f;
1551
1552         assert(j);
1553         assert(j->no_new_files);
1554
1555         /* Simply adds all directories for files we have open as
1556          * "root" directories. We don't expect errors here, so we
1557          * treat them as fatal. */
1558
1559         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1560                 _cleanup_free_ char *dir;
1561                 int r;
1562
1563                 dir = dirname_malloc(f->path);
1564                 if (!dir)
1565                         return -ENOMEM;
1566
1567                 r = add_root_directory(j, dir);
1568                 if (r < 0) {
1569                         set_put_error(j, r);
1570                         return r;
1571                 }
1572         }
1573
1574         return 0;
1575 }
1576
1577
1578 static int allocate_inotify(sd_journal *j) {
1579         assert(j);
1580
1581         if (j->inotify_fd < 0) {
1582                 j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1583                 if (j->inotify_fd < 0)
1584                         return -errno;
1585         }
1586
1587         if (!j->directories_by_wd) {
1588                 j->directories_by_wd = hashmap_new(NULL);
1589                 if (!j->directories_by_wd)
1590                         return -ENOMEM;
1591         }
1592
1593         return 0;
1594 }
1595
1596 static sd_journal *journal_new(int flags, const char *path) {
1597         sd_journal *j;
1598
1599         j = new0(sd_journal, 1);
1600         if (!j)
1601                 return NULL;
1602
1603         j->original_pid = getpid();
1604         j->inotify_fd = -1;
1605         j->flags = flags;
1606         j->data_threshold = DEFAULT_DATA_THRESHOLD;
1607
1608         if (path) {
1609                 j->path = strdup(path);
1610                 if (!j->path)
1611                         goto fail;
1612         }
1613
1614         j->files = ordered_hashmap_new(&string_hash_ops);
1615         j->directories_by_path = hashmap_new(&string_hash_ops);
1616         j->mmap = mmap_cache_new();
1617         if (!j->files || !j->directories_by_path || !j->mmap)
1618                 goto fail;
1619
1620         return j;
1621
1622 fail:
1623         sd_journal_close(j);
1624         return NULL;
1625 }
1626
1627 _public_ int sd_journal_open(sd_journal **ret, int flags) {
1628         sd_journal *j;
1629         int r;
1630
1631         assert_return(ret, -EINVAL);
1632         assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL);
1633
1634         j = journal_new(flags, NULL);
1635         if (!j)
1636                 return -ENOMEM;
1637
1638         r = add_search_paths(j);
1639         if (r < 0)
1640                 goto fail;
1641
1642         *ret = j;
1643         return 0;
1644
1645 fail:
1646         sd_journal_close(j);
1647
1648         return r;
1649 }
1650
1651 _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
1652         _cleanup_free_ char *root = NULL, *class = NULL;
1653         sd_journal *j;
1654         char *p;
1655         int r;
1656
1657         assert_return(machine, -EINVAL);
1658         assert_return(ret, -EINVAL);
1659         assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL);
1660         assert_return(machine_name_is_valid(machine), -EINVAL);
1661
1662         p = strappenda("/run/systemd/machines/", machine);
1663         r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL);
1664         if (r == -ENOENT)
1665                 return -EHOSTDOWN;
1666         if (r < 0)
1667                 return r;
1668         if (!root)
1669                 return -ENODATA;
1670
1671         if (!streq_ptr(class, "container"))
1672                 return -EIO;
1673
1674         j = journal_new(flags, NULL);
1675         if (!j)
1676                 return -ENOMEM;
1677
1678         j->prefix = root;
1679         root = NULL;
1680
1681         r = add_search_paths(j);
1682         if (r < 0)
1683                 goto fail;
1684
1685         *ret = j;
1686         return 0;
1687
1688 fail:
1689         sd_journal_close(j);
1690         return r;
1691 }
1692
1693 _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
1694         sd_journal *j;
1695         int r;
1696
1697         assert_return(ret, -EINVAL);
1698         assert_return(path, -EINVAL);
1699         assert_return(flags == 0, -EINVAL);
1700
1701         j = journal_new(flags, path);
1702         if (!j)
1703                 return -ENOMEM;
1704
1705         r = add_root_directory(j, path);
1706         if (r < 0) {
1707                 set_put_error(j, r);
1708                 goto fail;
1709         }
1710
1711         *ret = j;
1712         return 0;
1713
1714 fail:
1715         sd_journal_close(j);
1716
1717         return r;
1718 }
1719
1720 _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
1721         sd_journal *j;
1722         const char **path;
1723         int r;
1724
1725         assert_return(ret, -EINVAL);
1726         assert_return(flags == 0, -EINVAL);
1727
1728         j = journal_new(flags, NULL);
1729         if (!j)
1730                 return -ENOMEM;
1731
1732         STRV_FOREACH(path, paths) {
1733                 r = add_any_file(j, *path);
1734                 if (r < 0) {
1735                         log_error_errno(r, "Failed to open %s: %m", *path);
1736                         goto fail;
1737                 }
1738         }
1739
1740         j->no_new_files = true;
1741
1742         *ret = j;
1743         return 0;
1744
1745 fail:
1746         sd_journal_close(j);
1747
1748         return r;
1749 }
1750
1751 _public_ void sd_journal_close(sd_journal *j) {
1752         Directory *d;
1753         JournalFile *f;
1754
1755         if (!j)
1756                 return;
1757
1758         sd_journal_flush_matches(j);
1759
1760         while ((f = ordered_hashmap_steal_first(j->files)))
1761                 journal_file_close(f);
1762
1763         ordered_hashmap_free(j->files);
1764
1765         while ((d = hashmap_first(j->directories_by_path)))
1766                 remove_directory(j, d);
1767
1768         while ((d = hashmap_first(j->directories_by_wd)))
1769                 remove_directory(j, d);
1770
1771         hashmap_free(j->directories_by_path);
1772         hashmap_free(j->directories_by_wd);
1773
1774         safe_close(j->inotify_fd);
1775
1776         if (j->mmap) {
1777                 log_debug("mmap cache statistics: %u hit, %u miss", mmap_cache_get_hit(j->mmap), mmap_cache_get_missed(j->mmap));
1778                 mmap_cache_unref(j->mmap);
1779         }
1780
1781         free(j->path);
1782         free(j->prefix);
1783         free(j->unique_field);
1784         set_free(j->errors);
1785         free(j);
1786 }
1787
1788 _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
1789         Object *o;
1790         JournalFile *f;
1791         int r;
1792
1793         assert_return(j, -EINVAL);
1794         assert_return(!journal_pid_changed(j), -ECHILD);
1795         assert_return(ret, -EINVAL);
1796
1797         f = j->current_file;
1798         if (!f)
1799                 return -EADDRNOTAVAIL;
1800
1801         if (f->current_offset <= 0)
1802                 return -EADDRNOTAVAIL;
1803
1804         r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
1805         if (r < 0)
1806                 return r;
1807
1808         *ret = le64toh(o->entry.realtime);
1809         return 0;
1810 }
1811
1812 _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) {
1813         Object *o;
1814         JournalFile *f;
1815         int r;
1816         sd_id128_t id;
1817
1818         assert_return(j, -EINVAL);
1819         assert_return(!journal_pid_changed(j), -ECHILD);
1820
1821         f = j->current_file;
1822         if (!f)
1823                 return -EADDRNOTAVAIL;
1824
1825         if (f->current_offset <= 0)
1826                 return -EADDRNOTAVAIL;
1827
1828         r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
1829         if (r < 0)
1830                 return r;
1831
1832         if (ret_boot_id)
1833                 *ret_boot_id = o->entry.boot_id;
1834         else {
1835                 r = sd_id128_get_boot(&id);
1836                 if (r < 0)
1837                         return r;
1838
1839                 if (!sd_id128_equal(id, o->entry.boot_id))
1840                         return -ESTALE;
1841         }
1842
1843         if (ret)
1844                 *ret = le64toh(o->entry.monotonic);
1845
1846         return 0;
1847 }
1848
1849 static bool field_is_valid(const char *field) {
1850         const char *p;
1851
1852         assert(field);
1853
1854         if (isempty(field))
1855                 return false;
1856
1857         if (startswith(field, "__"))
1858                 return false;
1859
1860         for (p = field; *p; p++) {
1861
1862                 if (*p == '_')
1863                         continue;
1864
1865                 if (*p >= 'A' && *p <= 'Z')
1866                         continue;
1867
1868                 if (*p >= '0' && *p <= '9')
1869                         continue;
1870
1871                 return false;
1872         }
1873
1874         return true;
1875 }
1876
1877 _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) {
1878         JournalFile *f;
1879         uint64_t i, n;
1880         size_t field_length;
1881         int r;
1882         Object *o;
1883
1884         assert_return(j, -EINVAL);
1885         assert_return(!journal_pid_changed(j), -ECHILD);
1886         assert_return(field, -EINVAL);
1887         assert_return(data, -EINVAL);
1888         assert_return(size, -EINVAL);
1889         assert_return(field_is_valid(field), -EINVAL);
1890
1891         f = j->current_file;
1892         if (!f)
1893                 return -EADDRNOTAVAIL;
1894
1895         if (f->current_offset <= 0)
1896                 return -EADDRNOTAVAIL;
1897
1898         r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
1899         if (r < 0)
1900                 return r;
1901
1902         field_length = strlen(field);
1903
1904         n = journal_file_entry_n_items(o);
1905         for (i = 0; i < n; i++) {
1906                 uint64_t p, l;
1907                 le64_t le_hash;
1908                 size_t t;
1909                 int compression;
1910
1911                 p = le64toh(o->entry.items[i].object_offset);
1912                 le_hash = o->entry.items[i].hash;
1913                 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
1914                 if (r < 0)
1915                         return r;
1916
1917                 if (le_hash != o->data.hash)
1918                         return -EBADMSG;
1919
1920                 l = le64toh(o->object.size) - offsetof(Object, data.payload);
1921
1922                 compression = o->object.flags & OBJECT_COMPRESSION_MASK;
1923                 if (compression) {
1924 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
1925                         if (decompress_startswith(compression,
1926                                                   o->data.payload, l,
1927                                                   &f->compress_buffer, &f->compress_buffer_size,
1928                                                   field, field_length, '=')) {
1929
1930                                 size_t rsize;
1931
1932                                 r = decompress_blob(compression,
1933                                                     o->data.payload, l,
1934                                                     &f->compress_buffer, &f->compress_buffer_size, &rsize,
1935                                                     j->data_threshold);
1936                                 if (r < 0)
1937                                         return r;
1938
1939                                 *data = f->compress_buffer;
1940                                 *size = (size_t) rsize;
1941
1942                                 return 0;
1943                         }
1944 #else
1945                         return -EPROTONOSUPPORT;
1946 #endif
1947                 } else if (l >= field_length+1 &&
1948                            memcmp(o->data.payload, field, field_length) == 0 &&
1949                            o->data.payload[field_length] == '=') {
1950
1951                         t = (size_t) l;
1952
1953                         if ((uint64_t) t != l)
1954                                 return -E2BIG;
1955
1956                         *data = o->data.payload;
1957                         *size = t;
1958
1959                         return 0;
1960                 }
1961
1962                 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
1963                 if (r < 0)
1964                         return r;
1965         }
1966
1967         return -ENOENT;
1968 }
1969
1970 static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **data, size_t *size) {
1971         size_t t;
1972         uint64_t l;
1973         int compression;
1974
1975         l = le64toh(o->object.size) - offsetof(Object, data.payload);
1976         t = (size_t) l;
1977
1978         /* We can't read objects larger than 4G on a 32bit machine */
1979         if ((uint64_t) t != l)
1980                 return -E2BIG;
1981
1982         compression = o->object.flags & OBJECT_COMPRESSION_MASK;
1983         if (compression) {
1984 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
1985                 size_t rsize;
1986                 int r;
1987
1988                 r = decompress_blob(compression,
1989                                     o->data.payload, l, &f->compress_buffer,
1990                                     &f->compress_buffer_size, &rsize, j->data_threshold);
1991                 if (r < 0)
1992                         return r;
1993
1994                 *data = f->compress_buffer;
1995                 *size = (size_t) rsize;
1996 #else
1997                 return -EPROTONOSUPPORT;
1998 #endif
1999         } else {
2000                 *data = o->data.payload;
2001                 *size = t;
2002         }
2003
2004         return 0;
2005 }
2006
2007 _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) {
2008         JournalFile *f;
2009         uint64_t p, n;
2010         le64_t le_hash;
2011         int r;
2012         Object *o;
2013
2014         assert_return(j, -EINVAL);
2015         assert_return(!journal_pid_changed(j), -ECHILD);
2016         assert_return(data, -EINVAL);
2017         assert_return(size, -EINVAL);
2018
2019         f = j->current_file;
2020         if (!f)
2021                 return -EADDRNOTAVAIL;
2022
2023         if (f->current_offset <= 0)
2024                 return -EADDRNOTAVAIL;
2025
2026         r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2027         if (r < 0)
2028                 return r;
2029
2030         n = journal_file_entry_n_items(o);
2031         if (j->current_field >= n)
2032                 return 0;
2033
2034         p = le64toh(o->entry.items[j->current_field].object_offset);
2035         le_hash = o->entry.items[j->current_field].hash;
2036         r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
2037         if (r < 0)
2038                 return r;
2039
2040         if (le_hash != o->data.hash)
2041                 return -EBADMSG;
2042
2043         r = return_data(j, f, o, data, size);
2044         if (r < 0)
2045                 return r;
2046
2047         j->current_field ++;
2048
2049         return 1;
2050 }
2051
2052 _public_ void sd_journal_restart_data(sd_journal *j) {
2053         if (!j)
2054                 return;
2055
2056         j->current_field = 0;
2057 }
2058
2059 _public_ int sd_journal_get_fd(sd_journal *j) {
2060         int r;
2061
2062         assert_return(j, -EINVAL);
2063         assert_return(!journal_pid_changed(j), -ECHILD);
2064
2065         if (j->inotify_fd >= 0)
2066                 return j->inotify_fd;
2067
2068         r = allocate_inotify(j);
2069         if (r < 0)
2070                 return r;
2071
2072         /* Iterate through all dirs again, to add them to the
2073          * inotify */
2074         if (j->no_new_files)
2075                 r = add_current_paths(j);
2076         else if (j->path)
2077                 r = add_root_directory(j, j->path);
2078         else
2079                 r = add_search_paths(j);
2080         if (r < 0)
2081                 return r;
2082
2083         return j->inotify_fd;
2084 }
2085
2086 _public_ int sd_journal_get_events(sd_journal *j) {
2087         int fd;
2088
2089         assert_return(j, -EINVAL);
2090         assert_return(!journal_pid_changed(j), -ECHILD);
2091
2092         fd = sd_journal_get_fd(j);
2093         if (fd < 0)
2094                 return fd;
2095
2096         return POLLIN;
2097 }
2098
2099 _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
2100         int fd;
2101
2102         assert_return(j, -EINVAL);
2103         assert_return(!journal_pid_changed(j), -ECHILD);
2104         assert_return(timeout_usec, -EINVAL);
2105
2106         fd = sd_journal_get_fd(j);
2107         if (fd < 0)
2108                 return fd;
2109
2110         if (!j->on_network) {
2111                 *timeout_usec = (uint64_t) -1;
2112                 return 0;
2113         }
2114
2115         /* If we are on the network we need to regularly check for
2116          * changes manually */
2117
2118         *timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC;
2119         return 1;
2120 }
2121
2122 static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
2123         Directory *d;
2124         int r;
2125
2126         assert(j);
2127         assert(e);
2128
2129         /* Is this a subdirectory we watch? */
2130         d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd));
2131         if (d) {
2132                 sd_id128_t id;
2133
2134                 if (!(e->mask & IN_ISDIR) && e->len > 0 &&
2135                     (endswith(e->name, ".journal") ||
2136                      endswith(e->name, ".journal~"))) {
2137
2138                         /* Event for a journal file */
2139
2140                         if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
2141                                 r = add_file(j, d->path, e->name);
2142                                 if (r < 0) {
2143                                         log_debug_errno(r, "Failed to add file %s/%s: %m",
2144                                                         d->path, e->name);
2145                                         set_put_error(j, r);
2146                                 }
2147
2148                         } else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) {
2149
2150                                 r = remove_file(j, d->path, e->name);
2151                                 if (r < 0)
2152                                         log_debug_errno(r, "Failed to remove file %s/%s: %m", d->path, e->name);
2153                         }
2154
2155                 } else if (!d->is_root && e->len == 0) {
2156
2157                         /* Event for a subdirectory */
2158
2159                         if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) {
2160                                 r = remove_directory(j, d);
2161                                 if (r < 0)
2162                                         log_debug_errno(r, "Failed to remove directory %s: %m", d->path);
2163                         }
2164
2165
2166                 } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) {
2167
2168                         /* Event for root directory */
2169
2170                         if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
2171                                 r = add_directory(j, d->path, e->name);
2172                                 if (r < 0)
2173                                         log_debug_errno(r, "Failed to add directory %s/%s: %m", d->path, e->name);
2174                         }
2175                 }
2176
2177                 return;
2178         }
2179
2180         if (e->mask & IN_IGNORED)
2181                 return;
2182
2183         log_warning("Unknown inotify event.");
2184 }
2185
2186 static int determine_change(sd_journal *j) {
2187         bool b;
2188
2189         assert(j);
2190
2191         b = j->current_invalidate_counter != j->last_invalidate_counter;
2192         j->last_invalidate_counter = j->current_invalidate_counter;
2193
2194         return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND;
2195 }
2196
2197 _public_ int sd_journal_process(sd_journal *j) {
2198         bool got_something = false;
2199
2200         assert_return(j, -EINVAL);
2201         assert_return(!journal_pid_changed(j), -ECHILD);
2202
2203         j->last_process_usec = now(CLOCK_MONOTONIC);
2204
2205         for (;;) {
2206                 uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event);
2207                 struct inotify_event *e;
2208                 ssize_t l;
2209
2210                 l = read(j->inotify_fd, buffer, sizeof(buffer));
2211                 if (l < 0) {
2212                         if (errno == EAGAIN || errno == EINTR)
2213                                 return got_something ? determine_change(j) : SD_JOURNAL_NOP;
2214
2215                         return -errno;
2216                 }
2217
2218                 got_something = true;
2219
2220                 FOREACH_INOTIFY_EVENT(e, buffer, l)
2221                         process_inotify_event(j, e);
2222         }
2223 }
2224
2225 _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
2226         int r;
2227         uint64_t t;
2228
2229         assert_return(j, -EINVAL);
2230         assert_return(!journal_pid_changed(j), -ECHILD);
2231
2232         if (j->inotify_fd < 0) {
2233
2234                 /* This is the first invocation, hence create the
2235                  * inotify watch */
2236                 r = sd_journal_get_fd(j);
2237                 if (r < 0)
2238                         return r;
2239
2240                 /* The journal might have changed since the context
2241                  * object was created and we weren't watching before,
2242                  * hence don't wait for anything, and return
2243                  * immediately. */
2244                 return determine_change(j);
2245         }
2246
2247         r = sd_journal_get_timeout(j, &t);
2248         if (r < 0)
2249                 return r;
2250
2251         if (t != (uint64_t) -1) {
2252                 usec_t n;
2253
2254                 n = now(CLOCK_MONOTONIC);
2255                 t = t > n ? t - n : 0;
2256
2257                 if (timeout_usec == (uint64_t) -1 || timeout_usec > t)
2258                         timeout_usec = t;
2259         }
2260
2261         do {
2262                 r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec);
2263         } while (r == -EINTR);
2264
2265         if (r < 0)
2266                 return r;
2267
2268         return sd_journal_process(j);
2269 }
2270
2271 _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) {
2272         Iterator i;
2273         JournalFile *f;
2274         bool first = true;
2275         uint64_t fmin = 0, tmax = 0;
2276         int r;
2277
2278         assert_return(j, -EINVAL);
2279         assert_return(!journal_pid_changed(j), -ECHILD);
2280         assert_return(from || to, -EINVAL);
2281         assert_return(from != to, -EINVAL);
2282
2283         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2284                 usec_t fr, t;
2285
2286                 r = journal_file_get_cutoff_realtime_usec(f, &fr, &t);
2287                 if (r == -ENOENT)
2288                         continue;
2289                 if (r < 0)
2290                         return r;
2291                 if (r == 0)
2292                         continue;
2293
2294                 if (first) {
2295                         fmin = fr;
2296                         tmax = t;
2297                         first = false;
2298                 } else {
2299                         fmin = MIN(fr, fmin);
2300                         tmax = MAX(t, tmax);
2301                 }
2302         }
2303
2304         if (from)
2305                 *from = fmin;
2306         if (to)
2307                 *to = tmax;
2308
2309         return first ? 0 : 1;
2310 }
2311
2312 _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) {
2313         Iterator i;
2314         JournalFile *f;
2315         bool found = false;
2316         int r;
2317
2318         assert_return(j, -EINVAL);
2319         assert_return(!journal_pid_changed(j), -ECHILD);
2320         assert_return(from || to, -EINVAL);
2321         assert_return(from != to, -EINVAL);
2322
2323         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2324                 usec_t fr, t;
2325
2326                 r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t);
2327                 if (r == -ENOENT)
2328                         continue;
2329                 if (r < 0)
2330                         return r;
2331                 if (r == 0)
2332                         continue;
2333
2334                 if (found) {
2335                         if (from)
2336                                 *from = MIN(fr, *from);
2337                         if (to)
2338                                 *to = MAX(t, *to);
2339                 } else {
2340                         if (from)
2341                                 *from = fr;
2342                         if (to)
2343                                 *to = t;
2344                         found = true;
2345                 }
2346         }
2347
2348         return found;
2349 }
2350
2351 void journal_print_header(sd_journal *j) {
2352         Iterator i;
2353         JournalFile *f;
2354         bool newline = false;
2355
2356         assert(j);
2357
2358         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2359                 if (newline)
2360                         putchar('\n');
2361                 else
2362                         newline = true;
2363
2364                 journal_file_print_header(f);
2365         }
2366 }
2367
2368 _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
2369         Iterator i;
2370         JournalFile *f;
2371         uint64_t sum = 0;
2372
2373         assert_return(j, -EINVAL);
2374         assert_return(!journal_pid_changed(j), -ECHILD);
2375         assert_return(bytes, -EINVAL);
2376
2377         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2378                 struct stat st;
2379
2380                 if (fstat(f->fd, &st) < 0)
2381                         return -errno;
2382
2383                 sum += (uint64_t) st.st_blocks * 512ULL;
2384         }
2385
2386         *bytes = sum;
2387         return 0;
2388 }
2389
2390 _public_ int sd_journal_query_unique(sd_journal *j, const char *field) {
2391         char *f;
2392
2393         assert_return(j, -EINVAL);
2394         assert_return(!journal_pid_changed(j), -ECHILD);
2395         assert_return(!isempty(field), -EINVAL);
2396         assert_return(field_is_valid(field), -EINVAL);
2397
2398         f = strdup(field);
2399         if (!f)
2400                 return -ENOMEM;
2401
2402         free(j->unique_field);
2403         j->unique_field = f;
2404         j->unique_file = NULL;
2405         j->unique_offset = 0;
2406         j->unique_file_lost = false;
2407
2408         return 0;
2409 }
2410
2411 _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) {
2412         size_t k;
2413
2414         assert_return(j, -EINVAL);
2415         assert_return(!journal_pid_changed(j), -ECHILD);
2416         assert_return(data, -EINVAL);
2417         assert_return(l, -EINVAL);
2418         assert_return(j->unique_field, -EINVAL);
2419
2420         k = strlen(j->unique_field);
2421
2422         if (!j->unique_file) {
2423                 if (j->unique_file_lost)
2424                         return 0;
2425
2426                 j->unique_file = ordered_hashmap_first(j->files);
2427                 if (!j->unique_file)
2428                         return 0;
2429
2430                 j->unique_offset = 0;
2431         }
2432
2433         for (;;) {
2434                 JournalFile *of;
2435                 Iterator i;
2436                 Object *o;
2437                 const void *odata;
2438                 size_t ol;
2439                 bool found;
2440                 int r;
2441
2442                 /* Proceed to next data object in the field's linked list */
2443                 if (j->unique_offset == 0) {
2444                         r = journal_file_find_field_object(j->unique_file, j->unique_field, k, &o, NULL);
2445                         if (r < 0)
2446                                 return r;
2447
2448                         j->unique_offset = r > 0 ? le64toh(o->field.head_data_offset) : 0;
2449                 } else {
2450                         r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o);
2451                         if (r < 0)
2452                                 return r;
2453
2454                         j->unique_offset = le64toh(o->data.next_field_offset);
2455                 }
2456
2457                 /* We reached the end of the list? Then start again, with the next file */
2458                 if (j->unique_offset == 0) {
2459                         j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
2460                         if (!j->unique_file)
2461                                 return 0;
2462
2463                         continue;
2464                 }
2465
2466                 /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED
2467                  * instead, so that we can look at this data object at the same
2468                  * time as one on another file */
2469                 r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o);
2470                 if (r < 0)
2471                         return r;
2472
2473                 /* Let's do the type check by hand, since we used 0 context above. */
2474                 if (o->object.type != OBJECT_DATA) {
2475                         log_debug("%s:offset " OFSfmt ": object has type %d, expected %d",
2476                                   j->unique_file->path, j->unique_offset,
2477                                   o->object.type, OBJECT_DATA);
2478                         return -EBADMSG;
2479                 }
2480
2481                 r = return_data(j, j->unique_file, o, &odata, &ol);
2482                 if (r < 0)
2483                         return r;
2484
2485                 /* Check if we have at least the field name and "=". */
2486                 if (ol <= k) {
2487                         log_debug("%s:offset " OFSfmt ": object has size %zu, expected at least %zu",
2488                                   j->unique_file->path, j->unique_offset,
2489                                   ol, k + 1);
2490                         return -EBADMSG;
2491                 }
2492
2493                 if (memcmp(odata, j->unique_field, k) || ((const char*) odata)[k] != '=') {
2494                         log_debug("%s:offset " OFSfmt ": object does not start with \"%s=\"",
2495                                   j->unique_file->path, j->unique_offset,
2496                                   j->unique_field);
2497                         return -EBADMSG;
2498                 }
2499
2500                 /* OK, now let's see if we already returned this data
2501                  * object by checking if it exists in the earlier
2502                  * traversed files. */
2503                 found = false;
2504                 ORDERED_HASHMAP_FOREACH(of, j->files, i) {
2505                         Object *oo;
2506                         uint64_t op;
2507
2508                         if (of == j->unique_file)
2509                                 break;
2510
2511                         /* Skip this file it didn't have any fields
2512                          * indexed */
2513                         if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) &&
2514                             le64toh(of->header->n_fields) <= 0)
2515                                 continue;
2516
2517                         r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), &oo, &op);
2518                         if (r < 0)
2519                                 return r;
2520
2521                         if (r > 0)
2522                                 found = true;
2523                 }
2524
2525                 if (found)
2526                         continue;
2527
2528                 r = return_data(j, j->unique_file, o, data, l);
2529                 if (r < 0)
2530                         return r;
2531
2532                 return 1;
2533         }
2534 }
2535
2536 _public_ void sd_journal_restart_unique(sd_journal *j) {
2537         if (!j)
2538                 return;
2539
2540         j->unique_file = NULL;
2541         j->unique_offset = 0;
2542         j->unique_file_lost = false;
2543 }
2544
2545 _public_ int sd_journal_reliable_fd(sd_journal *j) {
2546         assert_return(j, -EINVAL);
2547         assert_return(!journal_pid_changed(j), -ECHILD);
2548
2549         return !j->on_network;
2550 }
2551
2552 static char *lookup_field(const char *field, void *userdata) {
2553         sd_journal *j = userdata;
2554         const void *data;
2555         size_t size, d;
2556         int r;
2557
2558         assert(field);
2559         assert(j);
2560
2561         r = sd_journal_get_data(j, field, &data, &size);
2562         if (r < 0 ||
2563             size > REPLACE_VAR_MAX)
2564                 return strdup(field);
2565
2566         d = strlen(field) + 1;
2567
2568         return strndup((const char*) data + d, size - d);
2569 }
2570
2571 _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) {
2572         const void *data;
2573         size_t size;
2574         sd_id128_t id;
2575         _cleanup_free_ char *text = NULL, *cid = NULL;
2576         char *t;
2577         int r;
2578
2579         assert_return(j, -EINVAL);
2580         assert_return(!journal_pid_changed(j), -ECHILD);
2581         assert_return(ret, -EINVAL);
2582
2583         r = sd_journal_get_data(j, "MESSAGE_ID", &data, &size);
2584         if (r < 0)
2585                 return r;
2586
2587         cid = strndup((const char*) data + 11, size - 11);
2588         if (!cid)
2589                 return -ENOMEM;
2590
2591         r = sd_id128_from_string(cid, &id);
2592         if (r < 0)
2593                 return r;
2594
2595         r = catalog_get(CATALOG_DATABASE, id, &text);
2596         if (r < 0)
2597                 return r;
2598
2599         t = replace_var(text, lookup_field, j);
2600         if (!t)
2601                 return -ENOMEM;
2602
2603         *ret = t;
2604         return 0;
2605 }
2606
2607 _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) {
2608         assert_return(ret, -EINVAL);
2609
2610         return catalog_get(CATALOG_DATABASE, id, ret);
2611 }
2612
2613 _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {
2614         assert_return(j, -EINVAL);
2615         assert_return(!journal_pid_changed(j), -ECHILD);
2616
2617         j->data_threshold = sz;
2618         return 0;
2619 }
2620
2621 _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) {
2622         assert_return(j, -EINVAL);
2623         assert_return(!journal_pid_changed(j), -ECHILD);
2624         assert_return(sz, -EINVAL);
2625
2626         *sz = j->data_threshold;
2627         return 0;
2628 }