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