]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/sd-journal.c
79ffd9cb3fa215baf8ec2423d9fd8582d9ad6685
[thirdparty/systemd.git] / src / journal / sd-journal.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2011 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <inttypes.h>
24 #include <linux/magic.h>
25 #include <poll.h>
26 #include <stddef.h>
27 #include <sys/inotify.h>
28 #include <sys/vfs.h>
29 #include <unistd.h>
30
31 #include "sd-journal.h"
32
33 #include "alloc-util.h"
34 #include "catalog.h"
35 #include "compress.h"
36 #include "dirent-util.h"
37 #include "fd-util.h"
38 #include "fileio.h"
39 #include "format-util.h"
40 #include "fs-util.h"
41 #include "hashmap.h"
42 #include "hostname-util.h"
43 #include "id128-util.h"
44 #include "io-util.h"
45 #include "journal-def.h"
46 #include "journal-file.h"
47 #include "journal-internal.h"
48 #include "list.h"
49 #include "lookup3.h"
50 #include "missing.h"
51 #include "path-util.h"
52 #include "process-util.h"
53 #include "replace-var.h"
54 #include "stat-util.h"
55 #include "stat-util.h"
56 #include "stdio-util.h"
57 #include "string-util.h"
58 #include "strv.h"
59
60 #define JOURNAL_FILES_MAX 7168
61
62 #define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC)
63
64 #define REPLACE_VAR_MAX 256
65
66 #define DEFAULT_DATA_THRESHOLD (64*1024)
67
68 static void remove_file_real(sd_journal *j, JournalFile *f);
69
70 static bool journal_pid_changed(sd_journal *j) {
71 assert(j);
72
73 /* We don't support people creating a journal object and
74 * keeping it around over a fork(). Let's complain. */
75
76 return j->original_pid != getpid_cached();
77 }
78
79 static int journal_put_error(sd_journal *j, int r, const char *path) {
80 char *copy;
81 int k;
82
83 /* Memorize an error we encountered, and store which
84 * file/directory it was generated from. Note that we store
85 * only *one* path per error code, as the error code is the
86 * key into the hashmap, and the path is the value. This means
87 * we keep track only of all error kinds, but not of all error
88 * locations. This has the benefit that the hashmap cannot
89 * grow beyond bounds.
90 *
91 * We return an error here only if we didn't manage to
92 * memorize the real error. */
93
94 if (r >= 0)
95 return r;
96
97 k = hashmap_ensure_allocated(&j->errors, NULL);
98 if (k < 0)
99 return k;
100
101 if (path) {
102 copy = strdup(path);
103 if (!copy)
104 return -ENOMEM;
105 } else
106 copy = NULL;
107
108 k = hashmap_put(j->errors, INT_TO_PTR(r), copy);
109 if (k < 0) {
110 free(copy);
111
112 if (k == -EEXIST)
113 return 0;
114
115 return k;
116 }
117
118 return 0;
119 }
120
121 static void detach_location(sd_journal *j) {
122 Iterator i;
123 JournalFile *f;
124
125 assert(j);
126
127 j->current_file = NULL;
128 j->current_field = 0;
129
130 ORDERED_HASHMAP_FOREACH(f, j->files, i)
131 journal_file_reset_location(f);
132 }
133
134 static void reset_location(sd_journal *j) {
135 assert(j);
136
137 detach_location(j);
138 zero(j->current_location);
139 }
140
141 static void init_location(Location *l, LocationType type, JournalFile *f, Object *o) {
142 assert(l);
143 assert(IN_SET(type, LOCATION_DISCRETE, LOCATION_SEEK));
144 assert(f);
145 assert(o->object.type == OBJECT_ENTRY);
146
147 l->type = type;
148 l->seqnum = le64toh(o->entry.seqnum);
149 l->seqnum_id = f->header->seqnum_id;
150 l->realtime = le64toh(o->entry.realtime);
151 l->monotonic = le64toh(o->entry.monotonic);
152 l->boot_id = o->entry.boot_id;
153 l->xor_hash = le64toh(o->entry.xor_hash);
154
155 l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
156 }
157
158 static void set_location(sd_journal *j, JournalFile *f, Object *o) {
159 assert(j);
160 assert(f);
161 assert(o);
162
163 init_location(&j->current_location, LOCATION_DISCRETE, f, o);
164
165 j->current_file = f;
166 j->current_field = 0;
167
168 /* Let f know its candidate entry was picked. */
169 assert(f->location_type == LOCATION_SEEK);
170 f->location_type = LOCATION_DISCRETE;
171 }
172
173 static int match_is_valid(const void *data, size_t size) {
174 const char *b, *p;
175
176 assert(data);
177
178 if (size < 2)
179 return false;
180
181 if (startswith(data, "__"))
182 return false;
183
184 b = data;
185 for (p = b; p < b + size; p++) {
186
187 if (*p == '=')
188 return p > b;
189
190 if (*p == '_')
191 continue;
192
193 if (*p >= 'A' && *p <= 'Z')
194 continue;
195
196 if (*p >= '0' && *p <= '9')
197 continue;
198
199 return false;
200 }
201
202 return false;
203 }
204
205 static bool same_field(const void *_a, size_t s, const void *_b, size_t t) {
206 const uint8_t *a = _a, *b = _b;
207 size_t j;
208
209 for (j = 0; j < s && j < t; j++) {
210
211 if (a[j] != b[j])
212 return false;
213
214 if (a[j] == '=')
215 return true;
216 }
217
218 assert_not_reached("\"=\" not found");
219 }
220
221 static Match *match_new(Match *p, MatchType t) {
222 Match *m;
223
224 m = new0(Match, 1);
225 if (!m)
226 return NULL;
227
228 m->type = t;
229
230 if (p) {
231 m->parent = p;
232 LIST_PREPEND(matches, p->matches, m);
233 }
234
235 return m;
236 }
237
238 static void match_free(Match *m) {
239 assert(m);
240
241 while (m->matches)
242 match_free(m->matches);
243
244 if (m->parent)
245 LIST_REMOVE(matches, m->parent->matches, m);
246
247 free(m->data);
248 free(m);
249 }
250
251 static void match_free_if_empty(Match *m) {
252 if (!m || m->matches)
253 return;
254
255 match_free(m);
256 }
257
258 _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) {
259 Match *l3, *l4, *add_here = NULL, *m;
260 le64_t le_hash;
261
262 assert_return(j, -EINVAL);
263 assert_return(!journal_pid_changed(j), -ECHILD);
264 assert_return(data, -EINVAL);
265
266 if (size == 0)
267 size = strlen(data);
268
269 assert_return(match_is_valid(data, size), -EINVAL);
270
271 /* level 0: AND term
272 * level 1: OR terms
273 * level 2: AND terms
274 * level 3: OR terms
275 * level 4: concrete matches */
276
277 if (!j->level0) {
278 j->level0 = match_new(NULL, MATCH_AND_TERM);
279 if (!j->level0)
280 return -ENOMEM;
281 }
282
283 if (!j->level1) {
284 j->level1 = match_new(j->level0, MATCH_OR_TERM);
285 if (!j->level1)
286 return -ENOMEM;
287 }
288
289 if (!j->level2) {
290 j->level2 = match_new(j->level1, MATCH_AND_TERM);
291 if (!j->level2)
292 return -ENOMEM;
293 }
294
295 assert(j->level0->type == MATCH_AND_TERM);
296 assert(j->level1->type == MATCH_OR_TERM);
297 assert(j->level2->type == MATCH_AND_TERM);
298
299 le_hash = htole64(hash64(data, size));
300
301 LIST_FOREACH(matches, l3, j->level2->matches) {
302 assert(l3->type == MATCH_OR_TERM);
303
304 LIST_FOREACH(matches, l4, l3->matches) {
305 assert(l4->type == MATCH_DISCRETE);
306
307 /* Exactly the same match already? Then ignore
308 * this addition */
309 if (l4->le_hash == le_hash &&
310 l4->size == size &&
311 memcmp(l4->data, data, size) == 0)
312 return 0;
313
314 /* Same field? Then let's add this to this OR term */
315 if (same_field(data, size, l4->data, l4->size)) {
316 add_here = l3;
317 break;
318 }
319 }
320
321 if (add_here)
322 break;
323 }
324
325 if (!add_here) {
326 add_here = match_new(j->level2, MATCH_OR_TERM);
327 if (!add_here)
328 goto fail;
329 }
330
331 m = match_new(add_here, MATCH_DISCRETE);
332 if (!m)
333 goto fail;
334
335 m->le_hash = le_hash;
336 m->size = size;
337 m->data = memdup(data, size);
338 if (!m->data)
339 goto fail;
340
341 detach_location(j);
342
343 return 0;
344
345 fail:
346 match_free_if_empty(add_here);
347 match_free_if_empty(j->level2);
348 match_free_if_empty(j->level1);
349 match_free_if_empty(j->level0);
350
351 return -ENOMEM;
352 }
353
354 _public_ int sd_journal_add_conjunction(sd_journal *j) {
355 assert_return(j, -EINVAL);
356 assert_return(!journal_pid_changed(j), -ECHILD);
357
358 if (!j->level0)
359 return 0;
360
361 if (!j->level1)
362 return 0;
363
364 if (!j->level1->matches)
365 return 0;
366
367 j->level1 = NULL;
368 j->level2 = NULL;
369
370 return 0;
371 }
372
373 _public_ int sd_journal_add_disjunction(sd_journal *j) {
374 assert_return(j, -EINVAL);
375 assert_return(!journal_pid_changed(j), -ECHILD);
376
377 if (!j->level0)
378 return 0;
379
380 if (!j->level1)
381 return 0;
382
383 if (!j->level2)
384 return 0;
385
386 if (!j->level2->matches)
387 return 0;
388
389 j->level2 = NULL;
390 return 0;
391 }
392
393 static char *match_make_string(Match *m) {
394 char *p = NULL, *r;
395 Match *i;
396 bool enclose = false;
397
398 if (!m)
399 return strdup("none");
400
401 if (m->type == MATCH_DISCRETE)
402 return strndup(m->data, m->size);
403
404 LIST_FOREACH(matches, i, m->matches) {
405 char *t, *k;
406
407 t = match_make_string(i);
408 if (!t)
409 return mfree(p);
410
411 if (p) {
412 k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t);
413 free(p);
414 free(t);
415
416 if (!k)
417 return NULL;
418
419 p = k;
420
421 enclose = true;
422 } else
423 p = t;
424 }
425
426 if (enclose) {
427 r = strjoin("(", p, ")");
428 free(p);
429 return r;
430 }
431
432 return p;
433 }
434
435 char *journal_make_match_string(sd_journal *j) {
436 assert(j);
437
438 return match_make_string(j->level0);
439 }
440
441 _public_ void sd_journal_flush_matches(sd_journal *j) {
442 if (!j)
443 return;
444
445 if (j->level0)
446 match_free(j->level0);
447
448 j->level0 = j->level1 = j->level2 = NULL;
449
450 detach_location(j);
451 }
452
453 _pure_ static int compare_with_location(JournalFile *f, Location *l) {
454 assert(f);
455 assert(l);
456 assert(f->location_type == LOCATION_SEEK);
457 assert(IN_SET(l->type, LOCATION_DISCRETE, LOCATION_SEEK));
458
459 if (l->monotonic_set &&
460 sd_id128_equal(f->current_boot_id, l->boot_id) &&
461 l->realtime_set &&
462 f->current_realtime == l->realtime &&
463 l->xor_hash_set &&
464 f->current_xor_hash == l->xor_hash)
465 return 0;
466
467 if (l->seqnum_set &&
468 sd_id128_equal(f->header->seqnum_id, l->seqnum_id)) {
469
470 if (f->current_seqnum < l->seqnum)
471 return -1;
472 if (f->current_seqnum > l->seqnum)
473 return 1;
474 }
475
476 if (l->monotonic_set &&
477 sd_id128_equal(f->current_boot_id, l->boot_id)) {
478
479 if (f->current_monotonic < l->monotonic)
480 return -1;
481 if (f->current_monotonic > l->monotonic)
482 return 1;
483 }
484
485 if (l->realtime_set) {
486
487 if (f->current_realtime < l->realtime)
488 return -1;
489 if (f->current_realtime > l->realtime)
490 return 1;
491 }
492
493 if (l->xor_hash_set) {
494
495 if (f->current_xor_hash < l->xor_hash)
496 return -1;
497 if (f->current_xor_hash > l->xor_hash)
498 return 1;
499 }
500
501 return 0;
502 }
503
504 static int next_for_match(
505 sd_journal *j,
506 Match *m,
507 JournalFile *f,
508 uint64_t after_offset,
509 direction_t direction,
510 Object **ret,
511 uint64_t *offset) {
512
513 int r;
514 uint64_t np = 0;
515 Object *n;
516
517 assert(j);
518 assert(m);
519 assert(f);
520
521 if (m->type == MATCH_DISCRETE) {
522 uint64_t dp;
523
524 r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
525 if (r <= 0)
526 return r;
527
528 return journal_file_move_to_entry_by_offset_for_data(f, dp, after_offset, direction, ret, offset);
529
530 } else if (m->type == MATCH_OR_TERM) {
531 Match *i;
532
533 /* Find the earliest match beyond after_offset */
534
535 LIST_FOREACH(matches, i, m->matches) {
536 uint64_t cp;
537
538 r = next_for_match(j, i, f, after_offset, direction, NULL, &cp);
539 if (r < 0)
540 return r;
541 else if (r > 0) {
542 if (np == 0 || (direction == DIRECTION_DOWN ? cp < np : cp > np))
543 np = cp;
544 }
545 }
546
547 if (np == 0)
548 return 0;
549
550 } else if (m->type == MATCH_AND_TERM) {
551 Match *i, *last_moved;
552
553 /* Always jump to the next matching entry and repeat
554 * this until we find an offset that matches for all
555 * matches. */
556
557 if (!m->matches)
558 return 0;
559
560 r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np);
561 if (r <= 0)
562 return r;
563
564 assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset);
565 last_moved = m->matches;
566
567 LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) {
568 uint64_t cp;
569
570 r = next_for_match(j, i, f, np, direction, NULL, &cp);
571 if (r <= 0)
572 return r;
573
574 assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np);
575 if (direction == DIRECTION_DOWN ? cp > np : cp < np) {
576 np = cp;
577 last_moved = i;
578 }
579 }
580 }
581
582 assert(np > 0);
583
584 r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
585 if (r < 0)
586 return r;
587
588 if (ret)
589 *ret = n;
590 if (offset)
591 *offset = np;
592
593 return 1;
594 }
595
596 static int find_location_for_match(
597 sd_journal *j,
598 Match *m,
599 JournalFile *f,
600 direction_t direction,
601 Object **ret,
602 uint64_t *offset) {
603
604 int r;
605
606 assert(j);
607 assert(m);
608 assert(f);
609
610 if (m->type == MATCH_DISCRETE) {
611 uint64_t dp;
612
613 r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
614 if (r <= 0)
615 return r;
616
617 /* FIXME: missing: find by monotonic */
618
619 if (j->current_location.type == LOCATION_HEAD)
620 return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset);
621 if (j->current_location.type == LOCATION_TAIL)
622 return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset);
623 if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
624 return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset);
625 if (j->current_location.monotonic_set) {
626 r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
627 if (r != -ENOENT)
628 return r;
629 }
630 if (j->current_location.realtime_set)
631 return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset);
632
633 return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset);
634
635 } else if (m->type == MATCH_OR_TERM) {
636 uint64_t np = 0;
637 Object *n;
638 Match *i;
639
640 /* Find the earliest match */
641
642 LIST_FOREACH(matches, i, m->matches) {
643 uint64_t cp;
644
645 r = find_location_for_match(j, i, f, direction, NULL, &cp);
646 if (r < 0)
647 return r;
648 else if (r > 0) {
649 if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
650 np = cp;
651 }
652 }
653
654 if (np == 0)
655 return 0;
656
657 r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
658 if (r < 0)
659 return r;
660
661 if (ret)
662 *ret = n;
663 if (offset)
664 *offset = np;
665
666 return 1;
667
668 } else {
669 Match *i;
670 uint64_t np = 0;
671
672 assert(m->type == MATCH_AND_TERM);
673
674 /* First jump to the last match, and then find the
675 * next one where all matches match */
676
677 if (!m->matches)
678 return 0;
679
680 LIST_FOREACH(matches, i, m->matches) {
681 uint64_t cp;
682
683 r = find_location_for_match(j, i, f, direction, NULL, &cp);
684 if (r <= 0)
685 return r;
686
687 if (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))
688 np = cp;
689 }
690
691 return next_for_match(j, m, f, np, direction, ret, offset);
692 }
693 }
694
695 static int find_location_with_matches(
696 sd_journal *j,
697 JournalFile *f,
698 direction_t direction,
699 Object **ret,
700 uint64_t *offset) {
701
702 int r;
703
704 assert(j);
705 assert(f);
706 assert(ret);
707 assert(offset);
708
709 if (!j->level0) {
710 /* No matches is simple */
711
712 if (j->current_location.type == LOCATION_HEAD)
713 return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset);
714 if (j->current_location.type == LOCATION_TAIL)
715 return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset);
716 if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
717 return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
718 if (j->current_location.monotonic_set) {
719 r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
720 if (r != -ENOENT)
721 return r;
722 }
723 if (j->current_location.realtime_set)
724 return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
725
726 return journal_file_next_entry(f, 0, direction, ret, offset);
727 } else
728 return find_location_for_match(j, j->level0, f, direction, ret, offset);
729 }
730
731 static int next_with_matches(
732 sd_journal *j,
733 JournalFile *f,
734 direction_t direction,
735 Object **ret,
736 uint64_t *offset) {
737
738 assert(j);
739 assert(f);
740 assert(ret);
741 assert(offset);
742
743 /* No matches is easy. We simple advance the file
744 * pointer by one. */
745 if (!j->level0)
746 return journal_file_next_entry(f, f->current_offset, direction, ret, offset);
747
748 /* If we have a match then we look for the next matching entry
749 * with an offset at least one step larger */
750 return next_for_match(j, j->level0, f,
751 direction == DIRECTION_DOWN ? f->current_offset + 1
752 : f->current_offset - 1,
753 direction, ret, offset);
754 }
755
756 static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction) {
757 Object *c;
758 uint64_t cp, n_entries;
759 int r;
760
761 assert(j);
762 assert(f);
763
764 n_entries = le64toh(f->header->n_entries);
765
766 /* If we hit EOF before, we don't need to look into this file again
767 * unless direction changed or new entries appeared. */
768 if (f->last_direction == direction && f->location_type == LOCATION_TAIL &&
769 n_entries == f->last_n_entries)
770 return 0;
771
772 f->last_n_entries = n_entries;
773
774 if (f->last_direction == direction && f->current_offset > 0) {
775 /* LOCATION_SEEK here means we did the work in a previous
776 * iteration and the current location already points to a
777 * candidate entry. */
778 if (f->location_type != LOCATION_SEEK) {
779 r = next_with_matches(j, f, direction, &c, &cp);
780 if (r <= 0)
781 return r;
782
783 journal_file_save_location(f, c, cp);
784 }
785 } else {
786 f->last_direction = direction;
787
788 r = find_location_with_matches(j, f, direction, &c, &cp);
789 if (r <= 0)
790 return r;
791
792 journal_file_save_location(f, c, cp);
793 }
794
795 /* OK, we found the spot, now let's advance until an entry
796 * that is actually different from what we were previously
797 * looking at. This is necessary to handle entries which exist
798 * in two (or more) journal files, and which shall all be
799 * suppressed but one. */
800
801 for (;;) {
802 bool found;
803
804 if (j->current_location.type == LOCATION_DISCRETE) {
805 int k;
806
807 k = compare_with_location(f, &j->current_location);
808
809 found = direction == DIRECTION_DOWN ? k > 0 : k < 0;
810 } else
811 found = true;
812
813 if (found)
814 return 1;
815
816 r = next_with_matches(j, f, direction, &c, &cp);
817 if (r <= 0)
818 return r;
819
820 journal_file_save_location(f, c, cp);
821 }
822 }
823
824 static int real_journal_next(sd_journal *j, direction_t direction) {
825 JournalFile *new_file = NULL;
826 unsigned i, n_files;
827 const void **files;
828 Object *o;
829 int r;
830
831 assert_return(j, -EINVAL);
832 assert_return(!journal_pid_changed(j), -ECHILD);
833
834 r = iterated_cache_get(j->files_cache, NULL, &files, &n_files);
835 if (r < 0)
836 return r;
837
838 for (i = 0; i < n_files; i++) {
839 JournalFile *f = (JournalFile *)files[i];
840 bool found;
841
842 r = next_beyond_location(j, f, direction);
843 if (r < 0) {
844 log_debug_errno(r, "Can't iterate through %s, ignoring: %m", f->path);
845 remove_file_real(j, f);
846 continue;
847 } else if (r == 0) {
848 f->location_type = LOCATION_TAIL;
849 continue;
850 }
851
852 if (!new_file)
853 found = true;
854 else {
855 int k;
856
857 k = journal_file_compare_locations(f, new_file);
858
859 found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
860 }
861
862 if (found)
863 new_file = f;
864 }
865
866 if (!new_file)
867 return 0;
868
869 r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_file->current_offset, &o);
870 if (r < 0)
871 return r;
872
873 set_location(j, new_file, o);
874
875 return 1;
876 }
877
878 _public_ int sd_journal_next(sd_journal *j) {
879 return real_journal_next(j, DIRECTION_DOWN);
880 }
881
882 _public_ int sd_journal_previous(sd_journal *j) {
883 return real_journal_next(j, DIRECTION_UP);
884 }
885
886 static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) {
887 int c = 0, r;
888
889 assert_return(j, -EINVAL);
890 assert_return(!journal_pid_changed(j), -ECHILD);
891
892 if (skip == 0) {
893 /* If this is not a discrete skip, then at least
894 * resolve the current location */
895 if (j->current_location.type != LOCATION_DISCRETE) {
896 r = real_journal_next(j, direction);
897 if (r < 0)
898 return r;
899 }
900
901 return 0;
902 }
903
904 do {
905 r = real_journal_next(j, direction);
906 if (r < 0)
907 return r;
908
909 if (r == 0)
910 return c;
911
912 skip--;
913 c++;
914 } while (skip > 0);
915
916 return c;
917 }
918
919 _public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) {
920 return real_journal_next_skip(j, DIRECTION_DOWN, skip);
921 }
922
923 _public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) {
924 return real_journal_next_skip(j, DIRECTION_UP, skip);
925 }
926
927 _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
928 Object *o;
929 int r;
930 char bid[33], sid[33];
931
932 assert_return(j, -EINVAL);
933 assert_return(!journal_pid_changed(j), -ECHILD);
934 assert_return(cursor, -EINVAL);
935
936 if (!j->current_file || j->current_file->current_offset <= 0)
937 return -EADDRNOTAVAIL;
938
939 r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
940 if (r < 0)
941 return r;
942
943 sd_id128_to_string(j->current_file->header->seqnum_id, sid);
944 sd_id128_to_string(o->entry.boot_id, bid);
945
946 if (asprintf(cursor,
947 "s=%s;i=%"PRIx64";b=%s;m=%"PRIx64";t=%"PRIx64";x=%"PRIx64,
948 sid, le64toh(o->entry.seqnum),
949 bid, le64toh(o->entry.monotonic),
950 le64toh(o->entry.realtime),
951 le64toh(o->entry.xor_hash)) < 0)
952 return -ENOMEM;
953
954 return 0;
955 }
956
957 _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
958 const char *word, *state;
959 size_t l;
960 unsigned long long seqnum, monotonic, realtime, xor_hash;
961 bool
962 seqnum_id_set = false,
963 seqnum_set = false,
964 boot_id_set = false,
965 monotonic_set = false,
966 realtime_set = false,
967 xor_hash_set = false;
968 sd_id128_t seqnum_id, boot_id;
969
970 assert_return(j, -EINVAL);
971 assert_return(!journal_pid_changed(j), -ECHILD);
972 assert_return(!isempty(cursor), -EINVAL);
973
974 FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
975 char *item;
976 int k = 0;
977
978 if (l < 2 || word[1] != '=')
979 return -EINVAL;
980
981 item = strndup(word, l);
982 if (!item)
983 return -ENOMEM;
984
985 switch (word[0]) {
986
987 case 's':
988 seqnum_id_set = true;
989 k = sd_id128_from_string(item+2, &seqnum_id);
990 break;
991
992 case 'i':
993 seqnum_set = true;
994 if (sscanf(item+2, "%llx", &seqnum) != 1)
995 k = -EINVAL;
996 break;
997
998 case 'b':
999 boot_id_set = true;
1000 k = sd_id128_from_string(item+2, &boot_id);
1001 break;
1002
1003 case 'm':
1004 monotonic_set = true;
1005 if (sscanf(item+2, "%llx", &monotonic) != 1)
1006 k = -EINVAL;
1007 break;
1008
1009 case 't':
1010 realtime_set = true;
1011 if (sscanf(item+2, "%llx", &realtime) != 1)
1012 k = -EINVAL;
1013 break;
1014
1015 case 'x':
1016 xor_hash_set = true;
1017 if (sscanf(item+2, "%llx", &xor_hash) != 1)
1018 k = -EINVAL;
1019 break;
1020 }
1021
1022 free(item);
1023
1024 if (k < 0)
1025 return k;
1026 }
1027
1028 if ((!seqnum_set || !seqnum_id_set) &&
1029 (!monotonic_set || !boot_id_set) &&
1030 !realtime_set)
1031 return -EINVAL;
1032
1033 reset_location(j);
1034
1035 j->current_location.type = LOCATION_SEEK;
1036
1037 if (realtime_set) {
1038 j->current_location.realtime = (uint64_t) realtime;
1039 j->current_location.realtime_set = true;
1040 }
1041
1042 if (seqnum_set && seqnum_id_set) {
1043 j->current_location.seqnum = (uint64_t) seqnum;
1044 j->current_location.seqnum_id = seqnum_id;
1045 j->current_location.seqnum_set = true;
1046 }
1047
1048 if (monotonic_set && boot_id_set) {
1049 j->current_location.monotonic = (uint64_t) monotonic;
1050 j->current_location.boot_id = boot_id;
1051 j->current_location.monotonic_set = true;
1052 }
1053
1054 if (xor_hash_set) {
1055 j->current_location.xor_hash = (uint64_t) xor_hash;
1056 j->current_location.xor_hash_set = true;
1057 }
1058
1059 return 0;
1060 }
1061
1062 _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
1063 int r;
1064 Object *o;
1065
1066 assert_return(j, -EINVAL);
1067 assert_return(!journal_pid_changed(j), -ECHILD);
1068 assert_return(!isempty(cursor), -EINVAL);
1069
1070 if (!j->current_file || j->current_file->current_offset <= 0)
1071 return -EADDRNOTAVAIL;
1072
1073 r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
1074 if (r < 0)
1075 return r;
1076
1077 for (;;) {
1078 _cleanup_free_ char *item = NULL;
1079 unsigned long long ll;
1080 sd_id128_t id;
1081 int k = 0;
1082
1083 r = extract_first_word(&cursor, &item, ";", EXTRACT_DONT_COALESCE_SEPARATORS);
1084 if (r < 0)
1085 return r;
1086
1087 if (r == 0)
1088 break;
1089
1090 if (strlen(item) < 2 || item[1] != '=')
1091 return -EINVAL;
1092
1093 switch (item[0]) {
1094
1095 case 's':
1096 k = sd_id128_from_string(item+2, &id);
1097 if (k < 0)
1098 return k;
1099 if (!sd_id128_equal(id, j->current_file->header->seqnum_id))
1100 return 0;
1101 break;
1102
1103 case 'i':
1104 if (sscanf(item+2, "%llx", &ll) != 1)
1105 return -EINVAL;
1106 if (ll != le64toh(o->entry.seqnum))
1107 return 0;
1108 break;
1109
1110 case 'b':
1111 k = sd_id128_from_string(item+2, &id);
1112 if (k < 0)
1113 return k;
1114 if (!sd_id128_equal(id, o->entry.boot_id))
1115 return 0;
1116 break;
1117
1118 case 'm':
1119 if (sscanf(item+2, "%llx", &ll) != 1)
1120 return -EINVAL;
1121 if (ll != le64toh(o->entry.monotonic))
1122 return 0;
1123 break;
1124
1125 case 't':
1126 if (sscanf(item+2, "%llx", &ll) != 1)
1127 return -EINVAL;
1128 if (ll != le64toh(o->entry.realtime))
1129 return 0;
1130 break;
1131
1132 case 'x':
1133 if (sscanf(item+2, "%llx", &ll) != 1)
1134 return -EINVAL;
1135 if (ll != le64toh(o->entry.xor_hash))
1136 return 0;
1137 break;
1138 }
1139 }
1140
1141 return 1;
1142 }
1143
1144 _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
1145 assert_return(j, -EINVAL);
1146 assert_return(!journal_pid_changed(j), -ECHILD);
1147
1148 reset_location(j);
1149 j->current_location.type = LOCATION_SEEK;
1150 j->current_location.boot_id = boot_id;
1151 j->current_location.monotonic = usec;
1152 j->current_location.monotonic_set = true;
1153
1154 return 0;
1155 }
1156
1157 _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
1158 assert_return(j, -EINVAL);
1159 assert_return(!journal_pid_changed(j), -ECHILD);
1160
1161 reset_location(j);
1162 j->current_location.type = LOCATION_SEEK;
1163 j->current_location.realtime = usec;
1164 j->current_location.realtime_set = true;
1165
1166 return 0;
1167 }
1168
1169 _public_ int sd_journal_seek_head(sd_journal *j) {
1170 assert_return(j, -EINVAL);
1171 assert_return(!journal_pid_changed(j), -ECHILD);
1172
1173 reset_location(j);
1174 j->current_location.type = LOCATION_HEAD;
1175
1176 return 0;
1177 }
1178
1179 _public_ int sd_journal_seek_tail(sd_journal *j) {
1180 assert_return(j, -EINVAL);
1181 assert_return(!journal_pid_changed(j), -ECHILD);
1182
1183 reset_location(j);
1184 j->current_location.type = LOCATION_TAIL;
1185
1186 return 0;
1187 }
1188
1189 static void check_network(sd_journal *j, int fd) {
1190 assert(j);
1191
1192 if (j->on_network)
1193 return;
1194
1195 j->on_network = fd_is_network_fs(fd);
1196 }
1197
1198 static bool file_has_type_prefix(const char *prefix, const char *filename) {
1199 const char *full, *tilded, *atted;
1200
1201 full = strjoina(prefix, ".journal");
1202 tilded = strjoina(full, "~");
1203 atted = strjoina(prefix, "@");
1204
1205 return streq(filename, full) ||
1206 streq(filename, tilded) ||
1207 startswith(filename, atted);
1208 }
1209
1210 static bool file_type_wanted(int flags, const char *filename) {
1211 assert(filename);
1212
1213 if (!endswith(filename, ".journal") && !endswith(filename, ".journal~"))
1214 return false;
1215
1216 /* no flags set → every type is OK */
1217 if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)))
1218 return true;
1219
1220 if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename))
1221 return true;
1222
1223 if (flags & SD_JOURNAL_CURRENT_USER) {
1224 char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1];
1225
1226 xsprintf(prefix, "user-"UID_FMT, getuid());
1227
1228 if (file_has_type_prefix(prefix, filename))
1229 return true;
1230 }
1231
1232 return false;
1233 }
1234
1235 static bool path_has_prefix(sd_journal *j, const char *path, const char *prefix) {
1236 assert(j);
1237 assert(path);
1238 assert(prefix);
1239
1240 if (j->toplevel_fd >= 0)
1241 return false;
1242
1243 return path_startswith(path, prefix);
1244 }
1245
1246 static void track_file_disposition(sd_journal *j, JournalFile *f) {
1247 assert(j);
1248 assert(f);
1249
1250 if (!j->has_runtime_files && path_has_prefix(j, f->path, "/run"))
1251 j->has_runtime_files = true;
1252 else if (!j->has_persistent_files && path_has_prefix(j, f->path, "/var"))
1253 j->has_persistent_files = true;
1254 }
1255
1256 static const char *skip_slash(const char *p) {
1257
1258 if (!p)
1259 return NULL;
1260
1261 while (*p == '/')
1262 p++;
1263
1264 return p;
1265 }
1266
1267 static int add_any_file(
1268 sd_journal *j,
1269 int fd,
1270 const char *path) {
1271
1272 bool close_fd = false;
1273 JournalFile *f;
1274 struct stat st;
1275 int r, k;
1276
1277 assert(j);
1278 assert(fd >= 0 || path);
1279
1280 if (fd < 0) {
1281 if (j->toplevel_fd >= 0)
1282 /* If there's a top-level fd defined make the path relative, explicitly, since otherwise
1283 * openat() ignores the first argument. */
1284
1285 fd = openat(j->toplevel_fd, skip_slash(path), O_RDONLY|O_CLOEXEC|O_NONBLOCK);
1286 else
1287 fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
1288 if (fd < 0) {
1289 r = log_debug_errno(errno, "Failed to open journal file %s: %m", path);
1290 goto finish;
1291 }
1292
1293 close_fd = true;
1294
1295 r = fd_nonblock(fd, false);
1296 if (r < 0) {
1297 r = log_debug_errno(errno, "Failed to turn off O_NONBLOCK for %s: %m", path);
1298 goto finish;
1299 }
1300 }
1301
1302 if (fstat(fd, &st) < 0) {
1303 r = log_debug_errno(errno, "Failed to fstat file '%s': %m", path);
1304 goto finish;
1305 }
1306
1307 r = stat_verify_regular(&st);
1308 if (r < 0) {
1309 log_debug_errno(r, "Refusing to open '%s', as it is not a regular file.", path);
1310 goto finish;
1311 }
1312
1313 f = ordered_hashmap_get(j->files, path);
1314 if (f) {
1315 if (f->last_stat.st_dev == st.st_dev &&
1316 f->last_stat.st_ino == st.st_ino) {
1317
1318 /* We already track this file, under the same path and with the same device/inode numbers, it's
1319 * hence really the same. Mark this file as seen in this generation. This is used to GC old
1320 * files in process_q_overflow() to detect journal files that are still there and discern them
1321 * from those which are gone. */
1322
1323 f->last_seen_generation = j->generation;
1324 r = 0;
1325 goto finish;
1326 }
1327
1328 /* So we tracked a file under this name, but it has a different inode/device. In that case, it got
1329 * replaced (probably due to rotation?), let's drop it hence from our list. */
1330 remove_file_real(j, f);
1331 f = NULL;
1332 }
1333
1334 if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
1335 log_debug("Too many open journal files, not adding %s.", path);
1336 r = -ETOOMANYREFS;
1337 goto finish;
1338 }
1339
1340 r = journal_file_open(fd, path, O_RDONLY, 0, false, 0, false, NULL, j->mmap, NULL, NULL, &f);
1341 if (r < 0) {
1342 log_debug_errno(r, "Failed to open journal file %s: %m", path);
1343 goto finish;
1344 }
1345
1346 /* journal_file_dump(f); */
1347
1348 r = ordered_hashmap_put(j->files, f->path, f);
1349 if (r < 0) {
1350 f->close_fd = false; /* make sure journal_file_close() doesn't close the caller's fd (or our own). We'll let the caller do that, or ourselves */
1351 (void) journal_file_close(f);
1352 goto finish;
1353 }
1354
1355 close_fd = false; /* the fd is now owned by the JournalFile object */
1356
1357 f->last_seen_generation = j->generation;
1358
1359 track_file_disposition(j, f);
1360 check_network(j, f->fd);
1361
1362 j->current_invalidate_counter++;
1363
1364 log_debug("File %s added.", f->path);
1365
1366 r = 0;
1367
1368 finish:
1369 if (close_fd)
1370 safe_close(fd);
1371
1372 if (r < 0) {
1373 k = journal_put_error(j, r, path);
1374 if (k < 0)
1375 return k;
1376 }
1377
1378 return r;
1379 }
1380
1381 static int add_file_by_name(
1382 sd_journal *j,
1383 const char *prefix,
1384 const char *filename) {
1385
1386 const char *path;
1387
1388 assert(j);
1389 assert(prefix);
1390 assert(filename);
1391
1392 if (j->no_new_files)
1393 return 0;
1394
1395 if (!file_type_wanted(j->flags, filename))
1396 return 0;
1397
1398 path = strjoina(prefix, "/", filename);
1399 return add_any_file(j, -1, path);
1400 }
1401
1402 static void remove_file_by_name(
1403 sd_journal *j,
1404 const char *prefix,
1405 const char *filename) {
1406
1407 const char *path;
1408 JournalFile *f;
1409
1410 assert(j);
1411 assert(prefix);
1412 assert(filename);
1413
1414 path = strjoina(prefix, "/", filename);
1415 f = ordered_hashmap_get(j->files, path);
1416 if (!f)
1417 return;
1418
1419 remove_file_real(j, f);
1420 }
1421
1422 static void remove_file_real(sd_journal *j, JournalFile *f) {
1423 assert(j);
1424 assert(f);
1425
1426 (void) ordered_hashmap_remove(j->files, f->path);
1427
1428 log_debug("File %s removed.", f->path);
1429
1430 if (j->current_file == f) {
1431 j->current_file = NULL;
1432 j->current_field = 0;
1433 }
1434
1435 if (j->unique_file == f) {
1436 /* Jump to the next unique_file or NULL if that one was last */
1437 j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
1438 j->unique_offset = 0;
1439 if (!j->unique_file)
1440 j->unique_file_lost = true;
1441 }
1442
1443 if (j->fields_file == f) {
1444 j->fields_file = ordered_hashmap_next(j->files, j->fields_file->path);
1445 j->fields_offset = 0;
1446 if (!j->fields_file)
1447 j->fields_file_lost = true;
1448 }
1449
1450 (void) journal_file_close(f);
1451
1452 j->current_invalidate_counter++;
1453 }
1454
1455 static int dirname_is_machine_id(const char *fn) {
1456 sd_id128_t id, machine;
1457 int r;
1458
1459 r = sd_id128_get_machine(&machine);
1460 if (r < 0)
1461 return r;
1462
1463 r = sd_id128_from_string(fn, &id);
1464 if (r < 0)
1465 return r;
1466
1467 return sd_id128_equal(id, machine);
1468 }
1469
1470 static bool dirent_is_journal_file(const struct dirent *de) {
1471 assert(de);
1472
1473 if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
1474 return false;
1475
1476 return endswith(de->d_name, ".journal") ||
1477 endswith(de->d_name, ".journal~");
1478 }
1479
1480 static bool dirent_is_id128_subdir(const struct dirent *de) {
1481 assert(de);
1482
1483 if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN))
1484 return false;
1485
1486 return id128_is_valid(de->d_name);
1487 }
1488
1489 static int directory_open(sd_journal *j, const char *path, DIR **ret) {
1490 DIR *d;
1491
1492 assert(j);
1493 assert(path);
1494 assert(ret);
1495
1496 if (j->toplevel_fd < 0)
1497 d = opendir(path);
1498 else
1499 /* Open the specified directory relative to the toplevel fd. Enforce that the path specified is
1500 * relative, by dropping the initial slash */
1501 d = xopendirat(j->toplevel_fd, skip_slash(path), 0);
1502 if (!d)
1503 return -errno;
1504
1505 *ret = d;
1506 return 0;
1507 }
1508
1509 static int add_directory(sd_journal *j, const char *prefix, const char *dirname);
1510
1511 static void directory_enumerate(sd_journal *j, Directory *m, DIR *d) {
1512 struct dirent *de;
1513
1514 assert(j);
1515 assert(m);
1516 assert(d);
1517
1518 FOREACH_DIRENT_ALL(de, d, goto fail) {
1519
1520 if (dirent_is_journal_file(de))
1521 (void) add_file_by_name(j, m->path, de->d_name);
1522
1523 if (m->is_root && dirent_is_id128_subdir(de))
1524 (void) add_directory(j, m->path, de->d_name);
1525 }
1526
1527 return;
1528
1529 fail:
1530 log_debug_errno(errno, "Failed to enumerate directory %s, ignoring: %m", m->path);
1531 }
1532
1533 static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) {
1534 int r;
1535
1536 assert(j);
1537 assert(m);
1538 assert(fd >= 0);
1539
1540 /* Watch this directory if that's enabled and if it not being watched yet. */
1541
1542 if (m->wd > 0) /* Already have a watch? */
1543 return;
1544 if (j->inotify_fd < 0) /* Not watching at all? */
1545 return;
1546
1547 m->wd = inotify_add_watch_fd(j->inotify_fd, fd, mask);
1548 if (m->wd < 0) {
1549 log_debug_errno(errno, "Failed to watch journal directory '%s', ignoring: %m", m->path);
1550 return;
1551 }
1552
1553 r = hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m);
1554 if (r == -EEXIST)
1555 log_debug_errno(r, "Directory '%s' already being watched under a different path, ignoring: %m", m->path);
1556 if (r < 0) {
1557 log_debug_errno(r, "Failed to add watch for journal directory '%s' to hashmap, ignoring: %m", m->path);
1558 (void) inotify_rm_watch(j->inotify_fd, m->wd);
1559 m->wd = -1;
1560 }
1561 }
1562
1563 static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
1564 _cleanup_free_ char *path = NULL;
1565 _cleanup_closedir_ DIR *d = NULL;
1566 Directory *m;
1567 int r, k;
1568
1569 assert(j);
1570 assert(prefix);
1571
1572 /* Adds a journal file directory to watch. If the directory is already tracked this updates the inotify watch
1573 * and reenumerates directory contents */
1574
1575 if (dirname)
1576 path = strjoin(prefix, "/", dirname);
1577 else
1578 path = strdup(prefix);
1579 if (!path) {
1580 r = -ENOMEM;
1581 goto fail;
1582 }
1583
1584 log_debug("Considering directory '%s'.", path);
1585
1586 /* We consider everything local that is in a directory for the local machine ID, or that is stored in /run */
1587 if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
1588 !((dirname && dirname_is_machine_id(dirname) > 0) || path_has_prefix(j, path, "/run")))
1589 return 0;
1590
1591 r = directory_open(j, path, &d);
1592 if (r < 0) {
1593 log_debug_errno(r, "Failed to open directory '%s': %m", path);
1594 goto fail;
1595 }
1596
1597 m = hashmap_get(j->directories_by_path, path);
1598 if (!m) {
1599 m = new0(Directory, 1);
1600 if (!m) {
1601 r = -ENOMEM;
1602 goto fail;
1603 }
1604
1605 m->is_root = false;
1606 m->path = path;
1607
1608 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1609 free(m);
1610 r = -ENOMEM;
1611 goto fail;
1612 }
1613
1614 path = NULL; /* avoid freeing in cleanup */
1615 j->current_invalidate_counter++;
1616
1617 log_debug("Directory %s added.", m->path);
1618
1619 } else if (m->is_root)
1620 return 0; /* Don't 'downgrade' from root directory */
1621
1622 m->last_seen_generation = j->generation;
1623
1624 directory_watch(j, m, dirfd(d),
1625 IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
1626 IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
1627 IN_ONLYDIR);
1628
1629 if (!j->no_new_files)
1630 directory_enumerate(j, m, d);
1631
1632 check_network(j, dirfd(d));
1633
1634 return 0;
1635
1636 fail:
1637 k = journal_put_error(j, r, path ?: prefix);
1638 if (k < 0)
1639 return k;
1640
1641 return r;
1642 }
1643
1644 static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
1645
1646 _cleanup_closedir_ DIR *d = NULL;
1647 Directory *m;
1648 int r, k;
1649
1650 assert(j);
1651
1652 /* Adds a root directory to our set of directories to use. If the root directory is already in the set, we
1653 * update the inotify logic, and renumerate the directory entries. This call may hence be called to initially
1654 * populate the set, as well as to update it later. */
1655
1656 if (p) {
1657 /* If there's a path specified, use it. */
1658
1659 log_debug("Considering root directory '%s'.", p);
1660
1661 if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
1662 !path_has_prefix(j, p, "/run"))
1663 return -EINVAL;
1664
1665 if (j->prefix)
1666 p = strjoina(j->prefix, p);
1667
1668 r = directory_open(j, p, &d);
1669 if (r == -ENOENT && missing_ok)
1670 return 0;
1671 if (r < 0) {
1672 log_debug_errno(r, "Failed to open root directory %s: %m", p);
1673 goto fail;
1674 }
1675 } else {
1676 int dfd;
1677
1678 /* If there's no path specified, then we use the top-level fd itself. We duplicate the fd here, since
1679 * opendir() will take possession of the fd, and close it, which we don't want. */
1680
1681 p = "."; /* store this as "." in the directories hashmap */
1682
1683 dfd = fcntl(j->toplevel_fd, F_DUPFD_CLOEXEC, 3);
1684 if (dfd < 0) {
1685 r = -errno;
1686 goto fail;
1687 }
1688
1689 d = fdopendir(dfd);
1690 if (!d) {
1691 r = -errno;
1692 safe_close(dfd);
1693 goto fail;
1694 }
1695
1696 rewinddir(d);
1697 }
1698
1699 m = hashmap_get(j->directories_by_path, p);
1700 if (!m) {
1701 m = new0(Directory, 1);
1702 if (!m) {
1703 r = -ENOMEM;
1704 goto fail;
1705 }
1706
1707 m->is_root = true;
1708
1709 m->path = strdup(p);
1710 if (!m->path) {
1711 free(m);
1712 r = -ENOMEM;
1713 goto fail;
1714 }
1715
1716 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1717 free(m->path);
1718 free(m);
1719 r = -ENOMEM;
1720 goto fail;
1721 }
1722
1723 j->current_invalidate_counter++;
1724
1725 log_debug("Root directory %s added.", m->path);
1726
1727 } else if (!m->is_root)
1728 return 0;
1729
1730 directory_watch(j, m, dirfd(d),
1731 IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
1732 IN_ONLYDIR);
1733
1734 if (!j->no_new_files)
1735 directory_enumerate(j, m, d);
1736
1737 check_network(j, dirfd(d));
1738
1739 return 0;
1740
1741 fail:
1742 k = journal_put_error(j, r, p);
1743 if (k < 0)
1744 return k;
1745
1746 return r;
1747 }
1748
1749 static void remove_directory(sd_journal *j, Directory *d) {
1750 assert(j);
1751
1752 if (d->wd > 0) {
1753 hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd));
1754
1755 if (j->inotify_fd >= 0)
1756 inotify_rm_watch(j->inotify_fd, d->wd);
1757 }
1758
1759 hashmap_remove(j->directories_by_path, d->path);
1760
1761 if (d->is_root)
1762 log_debug("Root directory %s removed.", d->path);
1763 else
1764 log_debug("Directory %s removed.", d->path);
1765
1766 free(d->path);
1767 free(d);
1768 }
1769
1770 static int add_search_paths(sd_journal *j) {
1771
1772 static const char search_paths[] =
1773 "/run/log/journal\0"
1774 "/var/log/journal\0";
1775 const char *p;
1776
1777 assert(j);
1778
1779 /* We ignore most errors here, since the idea is to only open
1780 * what's actually accessible, and ignore the rest. */
1781
1782 NULSTR_FOREACH(p, search_paths)
1783 (void) add_root_directory(j, p, true);
1784
1785 if (!(j->flags & SD_JOURNAL_LOCAL_ONLY))
1786 (void) add_root_directory(j, "/var/log/journal/remote", true);
1787
1788 return 0;
1789 }
1790
1791 static int add_current_paths(sd_journal *j) {
1792 Iterator i;
1793 JournalFile *f;
1794
1795 assert(j);
1796 assert(j->no_new_files);
1797
1798 /* Simply adds all directories for files we have open as directories. We don't expect errors here, so we
1799 * treat them as fatal. */
1800
1801 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1802 _cleanup_free_ char *dir;
1803 int r;
1804
1805 dir = dirname_malloc(f->path);
1806 if (!dir)
1807 return -ENOMEM;
1808
1809 r = add_directory(j, dir, NULL);
1810 if (r < 0)
1811 return r;
1812 }
1813
1814 return 0;
1815 }
1816
1817 static int allocate_inotify(sd_journal *j) {
1818 assert(j);
1819
1820 if (j->inotify_fd < 0) {
1821 j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1822 if (j->inotify_fd < 0)
1823 return -errno;
1824 }
1825
1826 return hashmap_ensure_allocated(&j->directories_by_wd, NULL);
1827 }
1828
1829 static sd_journal *journal_new(int flags, const char *path) {
1830 sd_journal *j;
1831
1832 j = new0(sd_journal, 1);
1833 if (!j)
1834 return NULL;
1835
1836 j->original_pid = getpid_cached();
1837 j->toplevel_fd = -1;
1838 j->inotify_fd = -1;
1839 j->flags = flags;
1840 j->data_threshold = DEFAULT_DATA_THRESHOLD;
1841
1842 if (path) {
1843 char *t;
1844
1845 t = strdup(path);
1846 if (!t)
1847 goto fail;
1848
1849 if (flags & SD_JOURNAL_OS_ROOT)
1850 j->prefix = t;
1851 else
1852 j->path = t;
1853 }
1854
1855 j->files = ordered_hashmap_new(&path_hash_ops);
1856 if (!j->files)
1857 goto fail;
1858
1859 j->files_cache = ordered_hashmap_iterated_cache_new(j->files);
1860 j->directories_by_path = hashmap_new(&path_hash_ops);
1861 j->mmap = mmap_cache_new();
1862 if (!j->files_cache || !j->directories_by_path || !j->mmap)
1863 goto fail;
1864
1865 return j;
1866
1867 fail:
1868 sd_journal_close(j);
1869 return NULL;
1870 }
1871
1872 #define OPEN_ALLOWED_FLAGS \
1873 (SD_JOURNAL_LOCAL_ONLY | \
1874 SD_JOURNAL_RUNTIME_ONLY | \
1875 SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)
1876
1877 _public_ int sd_journal_open(sd_journal **ret, int flags) {
1878 sd_journal *j;
1879 int r;
1880
1881 assert_return(ret, -EINVAL);
1882 assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL);
1883
1884 j = journal_new(flags, NULL);
1885 if (!j)
1886 return -ENOMEM;
1887
1888 r = add_search_paths(j);
1889 if (r < 0)
1890 goto fail;
1891
1892 *ret = j;
1893 return 0;
1894
1895 fail:
1896 sd_journal_close(j);
1897
1898 return r;
1899 }
1900
1901 #define OPEN_CONTAINER_ALLOWED_FLAGS \
1902 (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM)
1903
1904 _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
1905 _cleanup_free_ char *root = NULL, *class = NULL;
1906 sd_journal *j;
1907 char *p;
1908 int r;
1909
1910 /* This is pretty much deprecated, people should use machined's OpenMachineRootDirectory() call instead in
1911 * combination with sd_journal_open_directory_fd(). */
1912
1913 assert_return(machine, -EINVAL);
1914 assert_return(ret, -EINVAL);
1915 assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL);
1916 assert_return(machine_name_is_valid(machine), -EINVAL);
1917
1918 p = strjoina("/run/systemd/machines/", machine);
1919 r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL);
1920 if (r == -ENOENT)
1921 return -EHOSTDOWN;
1922 if (r < 0)
1923 return r;
1924 if (!root)
1925 return -ENODATA;
1926
1927 if (!streq_ptr(class, "container"))
1928 return -EIO;
1929
1930 j = journal_new(flags, root);
1931 if (!j)
1932 return -ENOMEM;
1933
1934 r = add_search_paths(j);
1935 if (r < 0)
1936 goto fail;
1937
1938 *ret = j;
1939 return 0;
1940
1941 fail:
1942 sd_journal_close(j);
1943 return r;
1944 }
1945
1946 #define OPEN_DIRECTORY_ALLOWED_FLAGS \
1947 (SD_JOURNAL_OS_ROOT | \
1948 SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
1949
1950 _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
1951 sd_journal *j;
1952 int r;
1953
1954 assert_return(ret, -EINVAL);
1955 assert_return(path, -EINVAL);
1956 assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL);
1957
1958 j = journal_new(flags, path);
1959 if (!j)
1960 return -ENOMEM;
1961
1962 if (flags & SD_JOURNAL_OS_ROOT)
1963 r = add_search_paths(j);
1964 else
1965 r = add_root_directory(j, path, false);
1966 if (r < 0)
1967 goto fail;
1968
1969 *ret = j;
1970 return 0;
1971
1972 fail:
1973 sd_journal_close(j);
1974 return r;
1975 }
1976
1977 _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
1978 sd_journal *j;
1979 const char **path;
1980 int r;
1981
1982 assert_return(ret, -EINVAL);
1983 assert_return(flags == 0, -EINVAL);
1984
1985 j = journal_new(flags, NULL);
1986 if (!j)
1987 return -ENOMEM;
1988
1989 STRV_FOREACH(path, paths) {
1990 r = add_any_file(j, -1, *path);
1991 if (r < 0)
1992 goto fail;
1993 }
1994
1995 j->no_new_files = true;
1996
1997 *ret = j;
1998 return 0;
1999
2000 fail:
2001 sd_journal_close(j);
2002 return r;
2003 }
2004
2005 #define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
2006 (SD_JOURNAL_OS_ROOT | \
2007 SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
2008
2009 _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
2010 sd_journal *j;
2011 struct stat st;
2012 int r;
2013
2014 assert_return(ret, -EINVAL);
2015 assert_return(fd >= 0, -EBADF);
2016 assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL);
2017
2018 if (fstat(fd, &st) < 0)
2019 return -errno;
2020
2021 if (!S_ISDIR(st.st_mode))
2022 return -EBADFD;
2023
2024 j = journal_new(flags, NULL);
2025 if (!j)
2026 return -ENOMEM;
2027
2028 j->toplevel_fd = fd;
2029
2030 if (flags & SD_JOURNAL_OS_ROOT)
2031 r = add_search_paths(j);
2032 else
2033 r = add_root_directory(j, NULL, false);
2034 if (r < 0)
2035 goto fail;
2036
2037 *ret = j;
2038 return 0;
2039
2040 fail:
2041 sd_journal_close(j);
2042 return r;
2043 }
2044
2045 _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
2046 Iterator iterator;
2047 JournalFile *f;
2048 sd_journal *j;
2049 unsigned i;
2050 int r;
2051
2052 assert_return(ret, -EINVAL);
2053 assert_return(n_fds > 0, -EBADF);
2054 assert_return(flags == 0, -EINVAL);
2055
2056 j = journal_new(flags, NULL);
2057 if (!j)
2058 return -ENOMEM;
2059
2060 for (i = 0; i < n_fds; i++) {
2061 struct stat st;
2062
2063 if (fds[i] < 0) {
2064 r = -EBADF;
2065 goto fail;
2066 }
2067
2068 if (fstat(fds[i], &st) < 0) {
2069 r = -errno;
2070 goto fail;
2071 }
2072
2073 r = stat_verify_regular(&st);
2074 if (r < 0)
2075 goto fail;
2076
2077 r = add_any_file(j, fds[i], NULL);
2078 if (r < 0)
2079 goto fail;
2080 }
2081
2082 j->no_new_files = true;
2083 j->no_inotify = true;
2084
2085 *ret = j;
2086 return 0;
2087
2088 fail:
2089 /* If we fail, make sure we don't take possession of the files we managed to make use of successfully, and they
2090 * remain open */
2091 ORDERED_HASHMAP_FOREACH(f, j->files, iterator)
2092 f->close_fd = false;
2093
2094 sd_journal_close(j);
2095 return r;
2096 }
2097
2098 _public_ void sd_journal_close(sd_journal *j) {
2099 Directory *d;
2100
2101 if (!j)
2102 return;
2103
2104 sd_journal_flush_matches(j);
2105
2106 ordered_hashmap_free_with_destructor(j->files, journal_file_close);
2107 iterated_cache_free(j->files_cache);
2108
2109 while ((d = hashmap_first(j->directories_by_path)))
2110 remove_directory(j, d);
2111
2112 while ((d = hashmap_first(j->directories_by_wd)))
2113 remove_directory(j, d);
2114
2115 hashmap_free(j->directories_by_path);
2116 hashmap_free(j->directories_by_wd);
2117
2118 safe_close(j->inotify_fd);
2119
2120 if (j->mmap) {
2121 log_debug("mmap cache statistics: %u hit, %u miss", mmap_cache_get_hit(j->mmap), mmap_cache_get_missed(j->mmap));
2122 mmap_cache_unref(j->mmap);
2123 }
2124
2125 hashmap_free_free(j->errors);
2126
2127 free(j->path);
2128 free(j->prefix);
2129 free(j->unique_field);
2130 free(j->fields_buffer);
2131 free(j);
2132 }
2133
2134 _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
2135 Object *o;
2136 JournalFile *f;
2137 int r;
2138
2139 assert_return(j, -EINVAL);
2140 assert_return(!journal_pid_changed(j), -ECHILD);
2141 assert_return(ret, -EINVAL);
2142
2143 f = j->current_file;
2144 if (!f)
2145 return -EADDRNOTAVAIL;
2146
2147 if (f->current_offset <= 0)
2148 return -EADDRNOTAVAIL;
2149
2150 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2151 if (r < 0)
2152 return r;
2153
2154 *ret = le64toh(o->entry.realtime);
2155 return 0;
2156 }
2157
2158 _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) {
2159 Object *o;
2160 JournalFile *f;
2161 int r;
2162 sd_id128_t id;
2163
2164 assert_return(j, -EINVAL);
2165 assert_return(!journal_pid_changed(j), -ECHILD);
2166
2167 f = j->current_file;
2168 if (!f)
2169 return -EADDRNOTAVAIL;
2170
2171 if (f->current_offset <= 0)
2172 return -EADDRNOTAVAIL;
2173
2174 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2175 if (r < 0)
2176 return r;
2177
2178 if (ret_boot_id)
2179 *ret_boot_id = o->entry.boot_id;
2180 else {
2181 r = sd_id128_get_boot(&id);
2182 if (r < 0)
2183 return r;
2184
2185 if (!sd_id128_equal(id, o->entry.boot_id))
2186 return -ESTALE;
2187 }
2188
2189 if (ret)
2190 *ret = le64toh(o->entry.monotonic);
2191
2192 return 0;
2193 }
2194
2195 static bool field_is_valid(const char *field) {
2196 const char *p;
2197
2198 assert(field);
2199
2200 if (isempty(field))
2201 return false;
2202
2203 if (startswith(field, "__"))
2204 return false;
2205
2206 for (p = field; *p; p++) {
2207
2208 if (*p == '_')
2209 continue;
2210
2211 if (*p >= 'A' && *p <= 'Z')
2212 continue;
2213
2214 if (*p >= '0' && *p <= '9')
2215 continue;
2216
2217 return false;
2218 }
2219
2220 return true;
2221 }
2222
2223 _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) {
2224 JournalFile *f;
2225 uint64_t i, n;
2226 size_t field_length;
2227 int r;
2228 Object *o;
2229
2230 assert_return(j, -EINVAL);
2231 assert_return(!journal_pid_changed(j), -ECHILD);
2232 assert_return(field, -EINVAL);
2233 assert_return(data, -EINVAL);
2234 assert_return(size, -EINVAL);
2235 assert_return(field_is_valid(field), -EINVAL);
2236
2237 f = j->current_file;
2238 if (!f)
2239 return -EADDRNOTAVAIL;
2240
2241 if (f->current_offset <= 0)
2242 return -EADDRNOTAVAIL;
2243
2244 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2245 if (r < 0)
2246 return r;
2247
2248 field_length = strlen(field);
2249
2250 n = journal_file_entry_n_items(o);
2251 for (i = 0; i < n; i++) {
2252 uint64_t p, l;
2253 le64_t le_hash;
2254 size_t t;
2255 int compression;
2256
2257 p = le64toh(o->entry.items[i].object_offset);
2258 le_hash = o->entry.items[i].hash;
2259 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
2260 if (r < 0)
2261 return r;
2262
2263 if (le_hash != o->data.hash)
2264 return -EBADMSG;
2265
2266 l = le64toh(o->object.size) - offsetof(Object, data.payload);
2267
2268 compression = o->object.flags & OBJECT_COMPRESSION_MASK;
2269 if (compression) {
2270 #if HAVE_XZ || HAVE_LZ4
2271 r = decompress_startswith(compression,
2272 o->data.payload, l,
2273 &f->compress_buffer, &f->compress_buffer_size,
2274 field, field_length, '=');
2275 if (r < 0)
2276 log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m",
2277 object_compressed_to_string(compression), l, p);
2278 else if (r > 0) {
2279
2280 size_t rsize;
2281
2282 r = decompress_blob(compression,
2283 o->data.payload, l,
2284 &f->compress_buffer, &f->compress_buffer_size, &rsize,
2285 j->data_threshold);
2286 if (r < 0)
2287 return r;
2288
2289 *data = f->compress_buffer;
2290 *size = (size_t) rsize;
2291
2292 return 0;
2293 }
2294 #else
2295 return -EPROTONOSUPPORT;
2296 #endif
2297 } else if (l >= field_length+1 &&
2298 memcmp(o->data.payload, field, field_length) == 0 &&
2299 o->data.payload[field_length] == '=') {
2300
2301 t = (size_t) l;
2302
2303 if ((uint64_t) t != l)
2304 return -E2BIG;
2305
2306 *data = o->data.payload;
2307 *size = t;
2308
2309 return 0;
2310 }
2311
2312 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2313 if (r < 0)
2314 return r;
2315 }
2316
2317 return -ENOENT;
2318 }
2319
2320 static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **data, size_t *size) {
2321 size_t t;
2322 uint64_t l;
2323 int compression;
2324
2325 l = le64toh(o->object.size) - offsetof(Object, data.payload);
2326 t = (size_t) l;
2327
2328 /* We can't read objects larger than 4G on a 32bit machine */
2329 if ((uint64_t) t != l)
2330 return -E2BIG;
2331
2332 compression = o->object.flags & OBJECT_COMPRESSION_MASK;
2333 if (compression) {
2334 #if HAVE_XZ || HAVE_LZ4
2335 size_t rsize;
2336 int r;
2337
2338 r = decompress_blob(compression,
2339 o->data.payload, l, &f->compress_buffer,
2340 &f->compress_buffer_size, &rsize, j->data_threshold);
2341 if (r < 0)
2342 return r;
2343
2344 *data = f->compress_buffer;
2345 *size = (size_t) rsize;
2346 #else
2347 return -EPROTONOSUPPORT;
2348 #endif
2349 } else {
2350 *data = o->data.payload;
2351 *size = t;
2352 }
2353
2354 return 0;
2355 }
2356
2357 _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) {
2358 JournalFile *f;
2359 uint64_t p, n;
2360 le64_t le_hash;
2361 int r;
2362 Object *o;
2363
2364 assert_return(j, -EINVAL);
2365 assert_return(!journal_pid_changed(j), -ECHILD);
2366 assert_return(data, -EINVAL);
2367 assert_return(size, -EINVAL);
2368
2369 f = j->current_file;
2370 if (!f)
2371 return -EADDRNOTAVAIL;
2372
2373 if (f->current_offset <= 0)
2374 return -EADDRNOTAVAIL;
2375
2376 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2377 if (r < 0)
2378 return r;
2379
2380 n = journal_file_entry_n_items(o);
2381 if (j->current_field >= n)
2382 return 0;
2383
2384 p = le64toh(o->entry.items[j->current_field].object_offset);
2385 le_hash = o->entry.items[j->current_field].hash;
2386 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
2387 if (r < 0)
2388 return r;
2389
2390 if (le_hash != o->data.hash)
2391 return -EBADMSG;
2392
2393 r = return_data(j, f, o, data, size);
2394 if (r < 0)
2395 return r;
2396
2397 j->current_field++;
2398
2399 return 1;
2400 }
2401
2402 _public_ void sd_journal_restart_data(sd_journal *j) {
2403 if (!j)
2404 return;
2405
2406 j->current_field = 0;
2407 }
2408
2409 static int reiterate_all_paths(sd_journal *j) {
2410 assert(j);
2411
2412 if (j->no_new_files)
2413 return add_current_paths(j);
2414
2415 if (j->flags & SD_JOURNAL_OS_ROOT)
2416 return add_search_paths(j);
2417
2418 if (j->toplevel_fd >= 0)
2419 return add_root_directory(j, NULL, false);
2420
2421 if (j->path)
2422 return add_root_directory(j, j->path, true);
2423
2424 return add_search_paths(j);
2425 }
2426
2427 _public_ int sd_journal_get_fd(sd_journal *j) {
2428 int r;
2429
2430 assert_return(j, -EINVAL);
2431 assert_return(!journal_pid_changed(j), -ECHILD);
2432
2433 if (j->no_inotify)
2434 return -EMEDIUMTYPE;
2435
2436 if (j->inotify_fd >= 0)
2437 return j->inotify_fd;
2438
2439 r = allocate_inotify(j);
2440 if (r < 0)
2441 return r;
2442
2443 log_debug("Reiterating files to get inotify watches established.");
2444
2445 /* Iterate through all dirs again, to add them to the inotify */
2446 r = reiterate_all_paths(j);
2447 if (r < 0)
2448 return r;
2449
2450 return j->inotify_fd;
2451 }
2452
2453 _public_ int sd_journal_get_events(sd_journal *j) {
2454 int fd;
2455
2456 assert_return(j, -EINVAL);
2457 assert_return(!journal_pid_changed(j), -ECHILD);
2458
2459 fd = sd_journal_get_fd(j);
2460 if (fd < 0)
2461 return fd;
2462
2463 return POLLIN;
2464 }
2465
2466 _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
2467 int fd;
2468
2469 assert_return(j, -EINVAL);
2470 assert_return(!journal_pid_changed(j), -ECHILD);
2471 assert_return(timeout_usec, -EINVAL);
2472
2473 fd = sd_journal_get_fd(j);
2474 if (fd < 0)
2475 return fd;
2476
2477 if (!j->on_network) {
2478 *timeout_usec = (uint64_t) -1;
2479 return 0;
2480 }
2481
2482 /* If we are on the network we need to regularly check for
2483 * changes manually */
2484
2485 *timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC;
2486 return 1;
2487 }
2488
2489 static void process_q_overflow(sd_journal *j) {
2490 JournalFile *f;
2491 Directory *m;
2492 Iterator i;
2493
2494 assert(j);
2495
2496 /* When the inotify queue overruns we need to enumerate and re-validate all journal files to bring our list
2497 * back in sync with what's on disk. For this we pick a new generation counter value. It'll be assigned to all
2498 * journal files we encounter. All journal files and all directories that don't carry it after reenumeration
2499 * are subject for unloading. */
2500
2501 log_debug("Inotify queue overrun, reiterating everything.");
2502
2503 j->generation++;
2504 (void) reiterate_all_paths(j);
2505
2506 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2507
2508 if (f->last_seen_generation == j->generation)
2509 continue;
2510
2511 log_debug("File '%s' hasn't been seen in this enumeration, removing.", f->path);
2512 remove_file_real(j, f);
2513 }
2514
2515 HASHMAP_FOREACH(m, j->directories_by_path, i) {
2516
2517 if (m->last_seen_generation == j->generation)
2518 continue;
2519
2520 if (m->is_root) /* Never GC root directories */
2521 continue;
2522
2523 log_debug("Directory '%s' hasn't been seen in this enumeration, removing.", f->path);
2524 remove_directory(j, m);
2525 }
2526
2527 log_debug("Reiteration complete.");
2528 }
2529
2530 static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
2531 Directory *d;
2532
2533 assert(j);
2534 assert(e);
2535
2536 if (e->mask & IN_Q_OVERFLOW) {
2537 process_q_overflow(j);
2538 return;
2539 }
2540
2541 /* Is this a subdirectory we watch? */
2542 d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd));
2543 if (d) {
2544 if (!(e->mask & IN_ISDIR) && e->len > 0 &&
2545 (endswith(e->name, ".journal") ||
2546 endswith(e->name, ".journal~"))) {
2547
2548 /* Event for a journal file */
2549
2550 if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
2551 (void) add_file_by_name(j, d->path, e->name);
2552 else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT))
2553 remove_file_by_name(j, d->path, e->name);
2554
2555 } else if (!d->is_root && e->len == 0) {
2556
2557 /* Event for a subdirectory */
2558
2559 if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT))
2560 remove_directory(j, d);
2561
2562 } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && id128_is_valid(e->name)) {
2563
2564 /* Event for root directory */
2565
2566 if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
2567 (void) add_directory(j, d->path, e->name);
2568 }
2569
2570 return;
2571 }
2572
2573 if (e->mask & IN_IGNORED)
2574 return;
2575
2576 log_debug("Unexpected inotify event.");
2577 }
2578
2579 static int determine_change(sd_journal *j) {
2580 bool b;
2581
2582 assert(j);
2583
2584 b = j->current_invalidate_counter != j->last_invalidate_counter;
2585 j->last_invalidate_counter = j->current_invalidate_counter;
2586
2587 return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND;
2588 }
2589
2590 _public_ int sd_journal_process(sd_journal *j) {
2591 bool got_something = false;
2592
2593 assert_return(j, -EINVAL);
2594 assert_return(!journal_pid_changed(j), -ECHILD);
2595
2596 if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */
2597 return 0;
2598
2599 j->last_process_usec = now(CLOCK_MONOTONIC);
2600 j->last_invalidate_counter = j->current_invalidate_counter;
2601
2602 for (;;) {
2603 union inotify_event_buffer buffer;
2604 struct inotify_event *e;
2605 ssize_t l;
2606
2607 l = read(j->inotify_fd, &buffer, sizeof(buffer));
2608 if (l < 0) {
2609 if (IN_SET(errno, EAGAIN, EINTR))
2610 return got_something ? determine_change(j) : SD_JOURNAL_NOP;
2611
2612 return -errno;
2613 }
2614
2615 got_something = true;
2616
2617 FOREACH_INOTIFY_EVENT(e, buffer, l)
2618 process_inotify_event(j, e);
2619 }
2620 }
2621
2622 _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
2623 int r;
2624 uint64_t t;
2625
2626 assert_return(j, -EINVAL);
2627 assert_return(!journal_pid_changed(j), -ECHILD);
2628
2629 if (j->inotify_fd < 0) {
2630
2631 /* This is the first invocation, hence create the
2632 * inotify watch */
2633 r = sd_journal_get_fd(j);
2634 if (r < 0)
2635 return r;
2636
2637 /* The journal might have changed since the context
2638 * object was created and we weren't watching before,
2639 * hence don't wait for anything, and return
2640 * immediately. */
2641 return determine_change(j);
2642 }
2643
2644 r = sd_journal_get_timeout(j, &t);
2645 if (r < 0)
2646 return r;
2647
2648 if (t != (uint64_t) -1) {
2649 usec_t n;
2650
2651 n = now(CLOCK_MONOTONIC);
2652 t = t > n ? t - n : 0;
2653
2654 if (timeout_usec == (uint64_t) -1 || timeout_usec > t)
2655 timeout_usec = t;
2656 }
2657
2658 do {
2659 r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec);
2660 } while (r == -EINTR);
2661
2662 if (r < 0)
2663 return r;
2664
2665 return sd_journal_process(j);
2666 }
2667
2668 _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) {
2669 Iterator i;
2670 JournalFile *f;
2671 bool first = true;
2672 uint64_t fmin = 0, tmax = 0;
2673 int r;
2674
2675 assert_return(j, -EINVAL);
2676 assert_return(!journal_pid_changed(j), -ECHILD);
2677 assert_return(from || to, -EINVAL);
2678 assert_return(from != to, -EINVAL);
2679
2680 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2681 usec_t fr, t;
2682
2683 r = journal_file_get_cutoff_realtime_usec(f, &fr, &t);
2684 if (r == -ENOENT)
2685 continue;
2686 if (r < 0)
2687 return r;
2688 if (r == 0)
2689 continue;
2690
2691 if (first) {
2692 fmin = fr;
2693 tmax = t;
2694 first = false;
2695 } else {
2696 fmin = MIN(fr, fmin);
2697 tmax = MAX(t, tmax);
2698 }
2699 }
2700
2701 if (from)
2702 *from = fmin;
2703 if (to)
2704 *to = tmax;
2705
2706 return first ? 0 : 1;
2707 }
2708
2709 _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) {
2710 Iterator i;
2711 JournalFile *f;
2712 bool found = false;
2713 int r;
2714
2715 assert_return(j, -EINVAL);
2716 assert_return(!journal_pid_changed(j), -ECHILD);
2717 assert_return(from || to, -EINVAL);
2718 assert_return(from != to, -EINVAL);
2719
2720 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2721 usec_t fr, t;
2722
2723 r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t);
2724 if (r == -ENOENT)
2725 continue;
2726 if (r < 0)
2727 return r;
2728 if (r == 0)
2729 continue;
2730
2731 if (found) {
2732 if (from)
2733 *from = MIN(fr, *from);
2734 if (to)
2735 *to = MAX(t, *to);
2736 } else {
2737 if (from)
2738 *from = fr;
2739 if (to)
2740 *to = t;
2741 found = true;
2742 }
2743 }
2744
2745 return found;
2746 }
2747
2748 void journal_print_header(sd_journal *j) {
2749 Iterator i;
2750 JournalFile *f;
2751 bool newline = false;
2752
2753 assert(j);
2754
2755 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2756 if (newline)
2757 putchar('\n');
2758 else
2759 newline = true;
2760
2761 journal_file_print_header(f);
2762 }
2763 }
2764
2765 _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
2766 Iterator i;
2767 JournalFile *f;
2768 uint64_t sum = 0;
2769
2770 assert_return(j, -EINVAL);
2771 assert_return(!journal_pid_changed(j), -ECHILD);
2772 assert_return(bytes, -EINVAL);
2773
2774 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2775 struct stat st;
2776
2777 if (fstat(f->fd, &st) < 0)
2778 return -errno;
2779
2780 sum += (uint64_t) st.st_blocks * 512ULL;
2781 }
2782
2783 *bytes = sum;
2784 return 0;
2785 }
2786
2787 _public_ int sd_journal_query_unique(sd_journal *j, const char *field) {
2788 char *f;
2789
2790 assert_return(j, -EINVAL);
2791 assert_return(!journal_pid_changed(j), -ECHILD);
2792 assert_return(!isempty(field), -EINVAL);
2793 assert_return(field_is_valid(field), -EINVAL);
2794
2795 f = strdup(field);
2796 if (!f)
2797 return -ENOMEM;
2798
2799 free(j->unique_field);
2800 j->unique_field = f;
2801 j->unique_file = NULL;
2802 j->unique_offset = 0;
2803 j->unique_file_lost = false;
2804
2805 return 0;
2806 }
2807
2808 _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) {
2809 size_t k;
2810
2811 assert_return(j, -EINVAL);
2812 assert_return(!journal_pid_changed(j), -ECHILD);
2813 assert_return(data, -EINVAL);
2814 assert_return(l, -EINVAL);
2815 assert_return(j->unique_field, -EINVAL);
2816
2817 k = strlen(j->unique_field);
2818
2819 if (!j->unique_file) {
2820 if (j->unique_file_lost)
2821 return 0;
2822
2823 j->unique_file = ordered_hashmap_first(j->files);
2824 if (!j->unique_file)
2825 return 0;
2826
2827 j->unique_offset = 0;
2828 }
2829
2830 for (;;) {
2831 JournalFile *of;
2832 Iterator i;
2833 Object *o;
2834 const void *odata;
2835 size_t ol;
2836 bool found;
2837 int r;
2838
2839 /* Proceed to next data object in the field's linked list */
2840 if (j->unique_offset == 0) {
2841 r = journal_file_find_field_object(j->unique_file, j->unique_field, k, &o, NULL);
2842 if (r < 0)
2843 return r;
2844
2845 j->unique_offset = r > 0 ? le64toh(o->field.head_data_offset) : 0;
2846 } else {
2847 r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o);
2848 if (r < 0)
2849 return r;
2850
2851 j->unique_offset = le64toh(o->data.next_field_offset);
2852 }
2853
2854 /* We reached the end of the list? Then start again, with the next file */
2855 if (j->unique_offset == 0) {
2856 j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
2857 if (!j->unique_file)
2858 return 0;
2859
2860 continue;
2861 }
2862
2863 /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED
2864 * instead, so that we can look at this data object at the same
2865 * time as one on another file */
2866 r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o);
2867 if (r < 0)
2868 return r;
2869
2870 /* Let's do the type check by hand, since we used 0 context above. */
2871 if (o->object.type != OBJECT_DATA) {
2872 log_debug("%s:offset " OFSfmt ": object has type %d, expected %d",
2873 j->unique_file->path, j->unique_offset,
2874 o->object.type, OBJECT_DATA);
2875 return -EBADMSG;
2876 }
2877
2878 r = return_data(j, j->unique_file, o, &odata, &ol);
2879 if (r < 0)
2880 return r;
2881
2882 /* Check if we have at least the field name and "=". */
2883 if (ol <= k) {
2884 log_debug("%s:offset " OFSfmt ": object has size %zu, expected at least %zu",
2885 j->unique_file->path, j->unique_offset,
2886 ol, k + 1);
2887 return -EBADMSG;
2888 }
2889
2890 if (memcmp(odata, j->unique_field, k) || ((const char*) odata)[k] != '=') {
2891 log_debug("%s:offset " OFSfmt ": object does not start with \"%s=\"",
2892 j->unique_file->path, j->unique_offset,
2893 j->unique_field);
2894 return -EBADMSG;
2895 }
2896
2897 /* OK, now let's see if we already returned this data
2898 * object by checking if it exists in the earlier
2899 * traversed files. */
2900 found = false;
2901 ORDERED_HASHMAP_FOREACH(of, j->files, i) {
2902 if (of == j->unique_file)
2903 break;
2904
2905 /* Skip this file it didn't have any fields indexed */
2906 if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0)
2907 continue;
2908
2909 r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), NULL, NULL);
2910 if (r < 0)
2911 return r;
2912 if (r > 0) {
2913 found = true;
2914 break;
2915 }
2916 }
2917
2918 if (found)
2919 continue;
2920
2921 r = return_data(j, j->unique_file, o, data, l);
2922 if (r < 0)
2923 return r;
2924
2925 return 1;
2926 }
2927 }
2928
2929 _public_ void sd_journal_restart_unique(sd_journal *j) {
2930 if (!j)
2931 return;
2932
2933 j->unique_file = NULL;
2934 j->unique_offset = 0;
2935 j->unique_file_lost = false;
2936 }
2937
2938 _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) {
2939 int r;
2940
2941 assert_return(j, -EINVAL);
2942 assert_return(!journal_pid_changed(j), -ECHILD);
2943 assert_return(field, -EINVAL);
2944
2945 if (!j->fields_file) {
2946 if (j->fields_file_lost)
2947 return 0;
2948
2949 j->fields_file = ordered_hashmap_first(j->files);
2950 if (!j->fields_file)
2951 return 0;
2952
2953 j->fields_hash_table_index = 0;
2954 j->fields_offset = 0;
2955 }
2956
2957 for (;;) {
2958 JournalFile *f, *of;
2959 Iterator i;
2960 uint64_t m;
2961 Object *o;
2962 size_t sz;
2963 bool found;
2964
2965 f = j->fields_file;
2966
2967 if (j->fields_offset == 0) {
2968 bool eof = false;
2969
2970 /* We are not yet positioned at any field. Let's pick the first one */
2971 r = journal_file_map_field_hash_table(f);
2972 if (r < 0)
2973 return r;
2974
2975 m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
2976 for (;;) {
2977 if (j->fields_hash_table_index >= m) {
2978 /* Reached the end of the hash table, go to the next file. */
2979 eof = true;
2980 break;
2981 }
2982
2983 j->fields_offset = le64toh(f->field_hash_table[j->fields_hash_table_index].head_hash_offset);
2984
2985 if (j->fields_offset != 0)
2986 break;
2987
2988 /* Empty hash table bucket, go to next one */
2989 j->fields_hash_table_index++;
2990 }
2991
2992 if (eof) {
2993 /* Proceed with next file */
2994 j->fields_file = ordered_hashmap_next(j->files, f->path);
2995 if (!j->fields_file) {
2996 *field = NULL;
2997 return 0;
2998 }
2999
3000 j->fields_offset = 0;
3001 j->fields_hash_table_index = 0;
3002 continue;
3003 }
3004
3005 } else {
3006 /* We are already positioned at a field. If so, let's figure out the next field from it */
3007
3008 r = journal_file_move_to_object(f, OBJECT_FIELD, j->fields_offset, &o);
3009 if (r < 0)
3010 return r;
3011
3012 j->fields_offset = le64toh(o->field.next_hash_offset);
3013 if (j->fields_offset == 0) {
3014 /* Reached the end of the hash table chain */
3015 j->fields_hash_table_index++;
3016 continue;
3017 }
3018 }
3019
3020 /* We use OBJECT_UNUSED here, so that the iterator below doesn't remove our mmap window */
3021 r = journal_file_move_to_object(f, OBJECT_UNUSED, j->fields_offset, &o);
3022 if (r < 0)
3023 return r;
3024
3025 /* Because we used OBJECT_UNUSED above, we need to do our type check manually */
3026 if (o->object.type != OBJECT_FIELD) {
3027 log_debug("%s:offset " OFSfmt ": object has type %i, expected %i", f->path, j->fields_offset, o->object.type, OBJECT_FIELD);
3028 return -EBADMSG;
3029 }
3030
3031 sz = le64toh(o->object.size) - offsetof(Object, field.payload);
3032
3033 /* Let's see if we already returned this field name before. */
3034 found = false;
3035 ORDERED_HASHMAP_FOREACH(of, j->files, i) {
3036 if (of == f)
3037 break;
3038
3039 /* Skip this file it didn't have any fields indexed */
3040 if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0)
3041 continue;
3042
3043 r = journal_file_find_field_object_with_hash(of, o->field.payload, sz, le64toh(o->field.hash), NULL, NULL);
3044 if (r < 0)
3045 return r;
3046 if (r > 0) {
3047 found = true;
3048 break;
3049 }
3050 }
3051
3052 if (found)
3053 continue;
3054
3055 /* Check if this is really a valid string containing no NUL byte */
3056 if (memchr(o->field.payload, 0, sz))
3057 return -EBADMSG;
3058
3059 if (sz > j->data_threshold)
3060 sz = j->data_threshold;
3061
3062 if (!GREEDY_REALLOC(j->fields_buffer, j->fields_buffer_allocated, sz + 1))
3063 return -ENOMEM;
3064
3065 memcpy(j->fields_buffer, o->field.payload, sz);
3066 j->fields_buffer[sz] = 0;
3067
3068 if (!field_is_valid(j->fields_buffer))
3069 return -EBADMSG;
3070
3071 *field = j->fields_buffer;
3072 return 1;
3073 }
3074 }
3075
3076 _public_ void sd_journal_restart_fields(sd_journal *j) {
3077 if (!j)
3078 return;
3079
3080 j->fields_file = NULL;
3081 j->fields_hash_table_index = 0;
3082 j->fields_offset = 0;
3083 j->fields_file_lost = false;
3084 }
3085
3086 _public_ int sd_journal_reliable_fd(sd_journal *j) {
3087 assert_return(j, -EINVAL);
3088 assert_return(!journal_pid_changed(j), -ECHILD);
3089
3090 return !j->on_network;
3091 }
3092
3093 static char *lookup_field(const char *field, void *userdata) {
3094 sd_journal *j = userdata;
3095 const void *data;
3096 size_t size, d;
3097 int r;
3098
3099 assert(field);
3100 assert(j);
3101
3102 r = sd_journal_get_data(j, field, &data, &size);
3103 if (r < 0 ||
3104 size > REPLACE_VAR_MAX)
3105 return strdup(field);
3106
3107 d = strlen(field) + 1;
3108
3109 return strndup((const char*) data + d, size - d);
3110 }
3111
3112 _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) {
3113 const void *data;
3114 size_t size;
3115 sd_id128_t id;
3116 _cleanup_free_ char *text = NULL, *cid = NULL;
3117 char *t;
3118 int r;
3119
3120 assert_return(j, -EINVAL);
3121 assert_return(!journal_pid_changed(j), -ECHILD);
3122 assert_return(ret, -EINVAL);
3123
3124 r = sd_journal_get_data(j, "MESSAGE_ID", &data, &size);
3125 if (r < 0)
3126 return r;
3127
3128 cid = strndup((const char*) data + 11, size - 11);
3129 if (!cid)
3130 return -ENOMEM;
3131
3132 r = sd_id128_from_string(cid, &id);
3133 if (r < 0)
3134 return r;
3135
3136 r = catalog_get(CATALOG_DATABASE, id, &text);
3137 if (r < 0)
3138 return r;
3139
3140 t = replace_var(text, lookup_field, j);
3141 if (!t)
3142 return -ENOMEM;
3143
3144 *ret = t;
3145 return 0;
3146 }
3147
3148 _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) {
3149 assert_return(ret, -EINVAL);
3150
3151 return catalog_get(CATALOG_DATABASE, id, ret);
3152 }
3153
3154 _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {
3155 assert_return(j, -EINVAL);
3156 assert_return(!journal_pid_changed(j), -ECHILD);
3157
3158 j->data_threshold = sz;
3159 return 0;
3160 }
3161
3162 _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) {
3163 assert_return(j, -EINVAL);
3164 assert_return(!journal_pid_changed(j), -ECHILD);
3165 assert_return(sz, -EINVAL);
3166
3167 *sz = j->data_threshold;
3168 return 0;
3169 }
3170
3171 _public_ int sd_journal_has_runtime_files(sd_journal *j) {
3172 assert_return(j, -EINVAL);
3173
3174 return j->has_runtime_files;
3175 }
3176
3177 _public_ int sd_journal_has_persistent_files(sd_journal *j) {
3178 assert_return(j, -EINVAL);
3179
3180 return j->has_persistent_files;
3181 }