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