]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/sd-journal.c
Merge pull request #8184 from poettering/color-ask-pw
[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 const char *skip_slash(const char *p) {
1247
1248 if (!p)
1249 return NULL;
1250
1251 while (*p == '/')
1252 p++;
1253
1254 return p;
1255 }
1256
1257 static int add_any_file(sd_journal *j, int fd, const char *path) {
1258 JournalFile *f = NULL;
1259 bool close_fd = false;
1260 int r, k;
1261
1262 assert(j);
1263 assert(fd >= 0 || path);
1264
1265 if (path) {
1266 f = ordered_hashmap_get(j->files, path);
1267 if (f) {
1268 /* Mark this file as seen in this generation. This is used to GC old files in
1269 * process_q_overflow() to detect journal files that are still and discern them from those who
1270 * are gone. */
1271 f->last_seen_generation = j->generation;
1272 return 0;
1273 }
1274 }
1275
1276 if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
1277 log_debug("Too many open journal files, not adding %s.", path);
1278 r = -ETOOMANYREFS;
1279 goto fail;
1280 }
1281
1282 if (fd < 0 && j->toplevel_fd >= 0) {
1283
1284 /* If there's a top-level fd defined, open the file relative to this now. (Make the path relative,
1285 * explicitly, since otherwise openat() ignores the first argument.) */
1286
1287 fd = openat(j->toplevel_fd, skip_slash(path), O_RDONLY|O_CLOEXEC);
1288 if (fd < 0) {
1289 r = log_debug_errno(errno, "Failed to open journal file %s: %m", path);
1290 goto fail;
1291 }
1292
1293 close_fd = true;
1294 }
1295
1296 r = journal_file_open(fd, path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, NULL, &f);
1297 if (r < 0) {
1298 if (close_fd)
1299 safe_close(fd);
1300 log_debug_errno(r, "Failed to open journal file %s: %m", path);
1301 goto fail;
1302 }
1303
1304 /* journal_file_dump(f); */
1305
1306 r = ordered_hashmap_put(j->files, f->path, f);
1307 if (r < 0) {
1308 f->close_fd = close_fd;
1309 (void) journal_file_close(f);
1310 goto fail;
1311 }
1312
1313 f->last_seen_generation = j->generation;
1314
1315 if (!j->has_runtime_files && path_has_prefix(j, f->path, "/run"))
1316 j->has_runtime_files = true;
1317 else if (!j->has_persistent_files && path_has_prefix(j, f->path, "/var"))
1318 j->has_persistent_files = true;
1319
1320 log_debug("File %s added.", f->path);
1321
1322 check_network(j, f->fd);
1323
1324 j->current_invalidate_counter++;
1325
1326 return 0;
1327
1328 fail:
1329 k = journal_put_error(j, r, path);
1330 if (k < 0)
1331 return k;
1332
1333 return r;
1334 }
1335
1336 static int add_file(sd_journal *j, const char *prefix, const char *filename) {
1337 const char *path;
1338
1339 assert(j);
1340 assert(prefix);
1341 assert(filename);
1342
1343 if (j->no_new_files)
1344 return 0;
1345
1346 if (!file_type_wanted(j->flags, filename))
1347 return 0;
1348
1349 path = strjoina(prefix, "/", filename);
1350 return add_any_file(j, -1, path);
1351 }
1352
1353 static void remove_file(sd_journal *j, const char *prefix, const char *filename) {
1354 const char *path;
1355 JournalFile *f;
1356
1357 assert(j);
1358 assert(prefix);
1359 assert(filename);
1360
1361 path = strjoina(prefix, "/", filename);
1362 f = ordered_hashmap_get(j->files, path);
1363 if (!f)
1364 return;
1365
1366 remove_file_real(j, f);
1367 }
1368
1369 static void remove_file_real(sd_journal *j, JournalFile *f) {
1370 assert(j);
1371 assert(f);
1372
1373 ordered_hashmap_remove(j->files, f->path);
1374
1375 log_debug("File %s removed.", f->path);
1376
1377 if (j->current_file == f) {
1378 j->current_file = NULL;
1379 j->current_field = 0;
1380 }
1381
1382 if (j->unique_file == f) {
1383 /* Jump to the next unique_file or NULL if that one was last */
1384 j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
1385 j->unique_offset = 0;
1386 if (!j->unique_file)
1387 j->unique_file_lost = true;
1388 }
1389
1390 if (j->fields_file == f) {
1391 j->fields_file = ordered_hashmap_next(j->files, j->fields_file->path);
1392 j->fields_offset = 0;
1393 if (!j->fields_file)
1394 j->fields_file_lost = true;
1395 }
1396
1397 (void) journal_file_close(f);
1398
1399 j->current_invalidate_counter++;
1400 }
1401
1402 static int dirname_is_machine_id(const char *fn) {
1403 sd_id128_t id, machine;
1404 int r;
1405
1406 r = sd_id128_get_machine(&machine);
1407 if (r < 0)
1408 return r;
1409
1410 r = sd_id128_from_string(fn, &id);
1411 if (r < 0)
1412 return r;
1413
1414 return sd_id128_equal(id, machine);
1415 }
1416
1417 static bool dirent_is_journal_file(const struct dirent *de) {
1418 assert(de);
1419
1420 if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
1421 return false;
1422
1423 return endswith(de->d_name, ".journal") ||
1424 endswith(de->d_name, ".journal~");
1425 }
1426
1427 static bool dirent_is_id128_subdir(const struct dirent *de) {
1428 assert(de);
1429
1430 if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN))
1431 return false;
1432
1433 return id128_is_valid(de->d_name);
1434 }
1435
1436 static int directory_open(sd_journal *j, const char *path, DIR **ret) {
1437 DIR *d;
1438
1439 assert(j);
1440 assert(path);
1441 assert(ret);
1442
1443 if (j->toplevel_fd < 0)
1444 d = opendir(path);
1445 else
1446 /* Open the specified directory relative to the toplevel fd. Enforce that the path specified is
1447 * relative, by dropping the initial slash */
1448 d = xopendirat(j->toplevel_fd, skip_slash(path), 0);
1449 if (!d)
1450 return -errno;
1451
1452 *ret = d;
1453 return 0;
1454 }
1455
1456 static int add_directory(sd_journal *j, const char *prefix, const char *dirname);
1457
1458 static void directory_enumerate(sd_journal *j, Directory *m, DIR *d) {
1459 struct dirent *de;
1460
1461 assert(j);
1462 assert(m);
1463 assert(d);
1464
1465 FOREACH_DIRENT_ALL(de, d, goto fail) {
1466 if (dirent_is_journal_file(de))
1467 (void) add_file(j, m->path, de->d_name);
1468
1469 if (m->is_root && dirent_is_id128_subdir(de))
1470 (void) add_directory(j, m->path, de->d_name);
1471 }
1472
1473 return;
1474
1475 fail:
1476 log_debug_errno(errno, "Failed to enumerate directory %s, ignoring: %m", m->path);
1477 }
1478
1479 static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) {
1480 int r;
1481
1482 assert(j);
1483 assert(m);
1484 assert(fd >= 0);
1485
1486 /* Watch this directory if that's enabled and if it not being watched yet. */
1487
1488 if (m->wd > 0) /* Already have a watch? */
1489 return;
1490 if (j->inotify_fd < 0) /* Not watching at all? */
1491 return;
1492
1493 m->wd = inotify_add_watch_fd(j->inotify_fd, fd, mask);
1494 if (m->wd < 0) {
1495 log_debug_errno(errno, "Failed to watch journal directory '%s', ignoring: %m", m->path);
1496 return;
1497 }
1498
1499 r = hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m);
1500 if (r == -EEXIST)
1501 log_debug_errno(r, "Directory '%s' already being watched under a different path, ignoring: %m", m->path);
1502 if (r < 0) {
1503 log_debug_errno(r, "Failed to add watch for journal directory '%s' to hashmap, ignoring: %m", m->path);
1504 (void) inotify_rm_watch(j->inotify_fd, m->wd);
1505 m->wd = -1;
1506 }
1507 }
1508
1509 static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
1510 _cleanup_free_ char *path = NULL;
1511 _cleanup_closedir_ DIR *d = NULL;
1512 Directory *m;
1513 int r, k;
1514
1515 assert(j);
1516 assert(prefix);
1517
1518 /* Adds a journal file directory to watch. If the directory is already tracked this updates the inotify watch
1519 * and reenumerates directory contents */
1520
1521 if (dirname)
1522 path = strjoin(prefix, "/", dirname);
1523 else
1524 path = strdup(prefix);
1525 if (!path) {
1526 r = -ENOMEM;
1527 goto fail;
1528 }
1529
1530 log_debug("Considering directory '%s'.", path);
1531
1532 /* We consider everything local that is in a directory for the local machine ID, or that is stored in /run */
1533 if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
1534 !((dirname && dirname_is_machine_id(dirname) > 0) || path_has_prefix(j, path, "/run")))
1535 return 0;
1536
1537 r = directory_open(j, path, &d);
1538 if (r < 0) {
1539 log_debug_errno(r, "Failed to open directory '%s': %m", path);
1540 goto fail;
1541 }
1542
1543 m = hashmap_get(j->directories_by_path, path);
1544 if (!m) {
1545 m = new0(Directory, 1);
1546 if (!m) {
1547 r = -ENOMEM;
1548 goto fail;
1549 }
1550
1551 m->is_root = false;
1552 m->path = path;
1553
1554 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1555 free(m);
1556 r = -ENOMEM;
1557 goto fail;
1558 }
1559
1560 path = NULL; /* avoid freeing in cleanup */
1561 j->current_invalidate_counter++;
1562
1563 log_debug("Directory %s added.", m->path);
1564
1565 } else if (m->is_root)
1566 return 0; /* Don't 'downgrade' from root directory */
1567
1568 m->last_seen_generation = j->generation;
1569
1570 directory_watch(j, m, dirfd(d),
1571 IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
1572 IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
1573 IN_ONLYDIR);
1574
1575 if (!j->no_new_files)
1576 directory_enumerate(j, m, d);
1577
1578 check_network(j, dirfd(d));
1579
1580 return 0;
1581
1582 fail:
1583 k = journal_put_error(j, r, path ?: prefix);
1584 if (k < 0)
1585 return k;
1586
1587 return r;
1588 }
1589
1590 static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
1591
1592 _cleanup_closedir_ DIR *d = NULL;
1593 Directory *m;
1594 int r, k;
1595
1596 assert(j);
1597
1598 /* Adds a root directory to our set of directories to use. If the root directory is already in the set, we
1599 * update the inotify logic, and renumerate the directory entries. This call may hence be called to initially
1600 * populate the set, as well as to update it later. */
1601
1602 if (p) {
1603 /* If there's a path specified, use it. */
1604
1605 log_debug("Considering root directory '%s'.", p);
1606
1607 if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
1608 !path_has_prefix(j, p, "/run"))
1609 return -EINVAL;
1610
1611 if (j->prefix)
1612 p = strjoina(j->prefix, p);
1613
1614 r = directory_open(j, p, &d);
1615 if (r == -ENOENT && missing_ok)
1616 return 0;
1617 if (r < 0) {
1618 log_debug_errno(r, "Failed to open root directory %s: %m", p);
1619 goto fail;
1620 }
1621 } else {
1622 int dfd;
1623
1624 /* If there's no path specified, then we use the top-level fd itself. We duplicate the fd here, since
1625 * opendir() will take possession of the fd, and close it, which we don't want. */
1626
1627 p = "."; /* store this as "." in the directories hashmap */
1628
1629 dfd = fcntl(j->toplevel_fd, F_DUPFD_CLOEXEC, 3);
1630 if (dfd < 0) {
1631 r = -errno;
1632 goto fail;
1633 }
1634
1635 d = fdopendir(dfd);
1636 if (!d) {
1637 r = -errno;
1638 safe_close(dfd);
1639 goto fail;
1640 }
1641
1642 rewinddir(d);
1643 }
1644
1645 m = hashmap_get(j->directories_by_path, p);
1646 if (!m) {
1647 m = new0(Directory, 1);
1648 if (!m) {
1649 r = -ENOMEM;
1650 goto fail;
1651 }
1652
1653 m->is_root = true;
1654
1655 m->path = strdup(p);
1656 if (!m->path) {
1657 free(m);
1658 r = -ENOMEM;
1659 goto fail;
1660 }
1661
1662 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1663 free(m->path);
1664 free(m);
1665 r = -ENOMEM;
1666 goto fail;
1667 }
1668
1669 j->current_invalidate_counter++;
1670
1671 log_debug("Root directory %s added.", m->path);
1672
1673 } else if (!m->is_root)
1674 return 0;
1675
1676 directory_watch(j, m, dirfd(d),
1677 IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
1678 IN_ONLYDIR);
1679
1680 if (!j->no_new_files)
1681 directory_enumerate(j, m, d);
1682
1683 check_network(j, dirfd(d));
1684
1685 return 0;
1686
1687 fail:
1688 k = journal_put_error(j, r, p);
1689 if (k < 0)
1690 return k;
1691
1692 return r;
1693 }
1694
1695 static void remove_directory(sd_journal *j, Directory *d) {
1696 assert(j);
1697
1698 if (d->wd > 0) {
1699 hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd));
1700
1701 if (j->inotify_fd >= 0)
1702 inotify_rm_watch(j->inotify_fd, d->wd);
1703 }
1704
1705 hashmap_remove(j->directories_by_path, d->path);
1706
1707 if (d->is_root)
1708 log_debug("Root directory %s removed.", d->path);
1709 else
1710 log_debug("Directory %s removed.", d->path);
1711
1712 free(d->path);
1713 free(d);
1714 }
1715
1716 static int add_search_paths(sd_journal *j) {
1717
1718 static const char search_paths[] =
1719 "/run/log/journal\0"
1720 "/var/log/journal\0";
1721 const char *p;
1722
1723 assert(j);
1724
1725 /* We ignore most errors here, since the idea is to only open
1726 * what's actually accessible, and ignore the rest. */
1727
1728 NULSTR_FOREACH(p, search_paths)
1729 (void) add_root_directory(j, p, true);
1730
1731 if (!(j->flags & SD_JOURNAL_LOCAL_ONLY))
1732 (void) add_root_directory(j, "/var/log/journal/remote", true);
1733
1734 return 0;
1735 }
1736
1737 static int add_current_paths(sd_journal *j) {
1738 Iterator i;
1739 JournalFile *f;
1740
1741 assert(j);
1742 assert(j->no_new_files);
1743
1744 /* Simply adds all directories for files we have open as directories. We don't expect errors here, so we
1745 * treat them as fatal. */
1746
1747 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1748 _cleanup_free_ char *dir;
1749 int r;
1750
1751 dir = dirname_malloc(f->path);
1752 if (!dir)
1753 return -ENOMEM;
1754
1755 r = add_directory(j, dir, NULL);
1756 if (r < 0)
1757 return r;
1758 }
1759
1760 return 0;
1761 }
1762
1763 static int allocate_inotify(sd_journal *j) {
1764 assert(j);
1765
1766 if (j->inotify_fd < 0) {
1767 j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1768 if (j->inotify_fd < 0)
1769 return -errno;
1770 }
1771
1772 return hashmap_ensure_allocated(&j->directories_by_wd, NULL);
1773 }
1774
1775 static sd_journal *journal_new(int flags, const char *path) {
1776 sd_journal *j;
1777
1778 j = new0(sd_journal, 1);
1779 if (!j)
1780 return NULL;
1781
1782 j->original_pid = getpid_cached();
1783 j->toplevel_fd = -1;
1784 j->inotify_fd = -1;
1785 j->flags = flags;
1786 j->data_threshold = DEFAULT_DATA_THRESHOLD;
1787
1788 if (path) {
1789 char *t;
1790
1791 t = strdup(path);
1792 if (!t)
1793 goto fail;
1794
1795 if (flags & SD_JOURNAL_OS_ROOT)
1796 j->prefix = t;
1797 else
1798 j->path = t;
1799 }
1800
1801 j->files = ordered_hashmap_new(&path_hash_ops);
1802 if (!j->files)
1803 goto fail;
1804
1805 j->files_cache = ordered_hashmap_iterated_cache_new(j->files);
1806 j->directories_by_path = hashmap_new(&path_hash_ops);
1807 j->mmap = mmap_cache_new();
1808 if (!j->files_cache || !j->directories_by_path || !j->mmap)
1809 goto fail;
1810
1811 return j;
1812
1813 fail:
1814 sd_journal_close(j);
1815 return NULL;
1816 }
1817
1818 #define OPEN_ALLOWED_FLAGS \
1819 (SD_JOURNAL_LOCAL_ONLY | \
1820 SD_JOURNAL_RUNTIME_ONLY | \
1821 SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)
1822
1823 _public_ int sd_journal_open(sd_journal **ret, int flags) {
1824 sd_journal *j;
1825 int r;
1826
1827 assert_return(ret, -EINVAL);
1828 assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL);
1829
1830 j = journal_new(flags, NULL);
1831 if (!j)
1832 return -ENOMEM;
1833
1834 r = add_search_paths(j);
1835 if (r < 0)
1836 goto fail;
1837
1838 *ret = j;
1839 return 0;
1840
1841 fail:
1842 sd_journal_close(j);
1843
1844 return r;
1845 }
1846
1847 #define OPEN_CONTAINER_ALLOWED_FLAGS \
1848 (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM)
1849
1850 _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
1851 _cleanup_free_ char *root = NULL, *class = NULL;
1852 sd_journal *j;
1853 char *p;
1854 int r;
1855
1856 /* This is pretty much deprecated, people should use machined's OpenMachineRootDirectory() call instead in
1857 * combination with sd_journal_open_directory_fd(). */
1858
1859 assert_return(machine, -EINVAL);
1860 assert_return(ret, -EINVAL);
1861 assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL);
1862 assert_return(machine_name_is_valid(machine), -EINVAL);
1863
1864 p = strjoina("/run/systemd/machines/", machine);
1865 r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL);
1866 if (r == -ENOENT)
1867 return -EHOSTDOWN;
1868 if (r < 0)
1869 return r;
1870 if (!root)
1871 return -ENODATA;
1872
1873 if (!streq_ptr(class, "container"))
1874 return -EIO;
1875
1876 j = journal_new(flags, root);
1877 if (!j)
1878 return -ENOMEM;
1879
1880 r = add_search_paths(j);
1881 if (r < 0)
1882 goto fail;
1883
1884 *ret = j;
1885 return 0;
1886
1887 fail:
1888 sd_journal_close(j);
1889 return r;
1890 }
1891
1892 #define OPEN_DIRECTORY_ALLOWED_FLAGS \
1893 (SD_JOURNAL_OS_ROOT | \
1894 SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
1895
1896 _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
1897 sd_journal *j;
1898 int r;
1899
1900 assert_return(ret, -EINVAL);
1901 assert_return(path, -EINVAL);
1902 assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL);
1903
1904 j = journal_new(flags, path);
1905 if (!j)
1906 return -ENOMEM;
1907
1908 if (flags & SD_JOURNAL_OS_ROOT)
1909 r = add_search_paths(j);
1910 else
1911 r = add_root_directory(j, path, false);
1912 if (r < 0)
1913 goto fail;
1914
1915 *ret = j;
1916 return 0;
1917
1918 fail:
1919 sd_journal_close(j);
1920 return r;
1921 }
1922
1923 _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
1924 sd_journal *j;
1925 const char **path;
1926 int r;
1927
1928 assert_return(ret, -EINVAL);
1929 assert_return(flags == 0, -EINVAL);
1930
1931 j = journal_new(flags, NULL);
1932 if (!j)
1933 return -ENOMEM;
1934
1935 STRV_FOREACH(path, paths) {
1936 r = add_any_file(j, -1, *path);
1937 if (r < 0)
1938 goto fail;
1939 }
1940
1941 j->no_new_files = true;
1942
1943 *ret = j;
1944 return 0;
1945
1946 fail:
1947 sd_journal_close(j);
1948 return r;
1949 }
1950
1951 #define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
1952 (SD_JOURNAL_OS_ROOT | \
1953 SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
1954
1955 _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
1956 sd_journal *j;
1957 struct stat st;
1958 int r;
1959
1960 assert_return(ret, -EINVAL);
1961 assert_return(fd >= 0, -EBADF);
1962 assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL);
1963
1964 if (fstat(fd, &st) < 0)
1965 return -errno;
1966
1967 if (!S_ISDIR(st.st_mode))
1968 return -EBADFD;
1969
1970 j = journal_new(flags, NULL);
1971 if (!j)
1972 return -ENOMEM;
1973
1974 j->toplevel_fd = fd;
1975
1976 if (flags & SD_JOURNAL_OS_ROOT)
1977 r = add_search_paths(j);
1978 else
1979 r = add_root_directory(j, NULL, false);
1980 if (r < 0)
1981 goto fail;
1982
1983 *ret = j;
1984 return 0;
1985
1986 fail:
1987 sd_journal_close(j);
1988 return r;
1989 }
1990
1991 _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
1992 Iterator iterator;
1993 JournalFile *f;
1994 sd_journal *j;
1995 unsigned i;
1996 int r;
1997
1998 assert_return(ret, -EINVAL);
1999 assert_return(n_fds > 0, -EBADF);
2000 assert_return(flags == 0, -EINVAL);
2001
2002 j = journal_new(flags, NULL);
2003 if (!j)
2004 return -ENOMEM;
2005
2006 for (i = 0; i < n_fds; i++) {
2007 struct stat st;
2008
2009 if (fds[i] < 0) {
2010 r = -EBADF;
2011 goto fail;
2012 }
2013
2014 if (fstat(fds[i], &st) < 0) {
2015 r = -errno;
2016 goto fail;
2017 }
2018
2019 if (!S_ISREG(st.st_mode)) {
2020 r = -EBADFD;
2021 goto fail;
2022 }
2023
2024 r = add_any_file(j, fds[i], NULL);
2025 if (r < 0)
2026 goto fail;
2027 }
2028
2029 j->no_new_files = true;
2030 j->no_inotify = true;
2031
2032 *ret = j;
2033 return 0;
2034
2035 fail:
2036 /* If we fail, make sure we don't take possession of the files we managed to make use of successfully, and they
2037 * remain open */
2038 ORDERED_HASHMAP_FOREACH(f, j->files, iterator)
2039 f->close_fd = false;
2040
2041 sd_journal_close(j);
2042 return r;
2043 }
2044
2045 _public_ void sd_journal_close(sd_journal *j) {
2046 Directory *d;
2047
2048 if (!j)
2049 return;
2050
2051 sd_journal_flush_matches(j);
2052
2053 ordered_hashmap_free_with_destructor(j->files, journal_file_close);
2054 iterated_cache_free(j->files_cache);
2055
2056 while ((d = hashmap_first(j->directories_by_path)))
2057 remove_directory(j, d);
2058
2059 while ((d = hashmap_first(j->directories_by_wd)))
2060 remove_directory(j, d);
2061
2062 hashmap_free(j->directories_by_path);
2063 hashmap_free(j->directories_by_wd);
2064
2065 safe_close(j->inotify_fd);
2066
2067 if (j->mmap) {
2068 log_debug("mmap cache statistics: %u hit, %u miss", mmap_cache_get_hit(j->mmap), mmap_cache_get_missed(j->mmap));
2069 mmap_cache_unref(j->mmap);
2070 }
2071
2072 hashmap_free_free(j->errors);
2073
2074 free(j->path);
2075 free(j->prefix);
2076 free(j->unique_field);
2077 free(j->fields_buffer);
2078 free(j);
2079 }
2080
2081 _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
2082 Object *o;
2083 JournalFile *f;
2084 int r;
2085
2086 assert_return(j, -EINVAL);
2087 assert_return(!journal_pid_changed(j), -ECHILD);
2088 assert_return(ret, -EINVAL);
2089
2090 f = j->current_file;
2091 if (!f)
2092 return -EADDRNOTAVAIL;
2093
2094 if (f->current_offset <= 0)
2095 return -EADDRNOTAVAIL;
2096
2097 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2098 if (r < 0)
2099 return r;
2100
2101 *ret = le64toh(o->entry.realtime);
2102 return 0;
2103 }
2104
2105 _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) {
2106 Object *o;
2107 JournalFile *f;
2108 int r;
2109 sd_id128_t id;
2110
2111 assert_return(j, -EINVAL);
2112 assert_return(!journal_pid_changed(j), -ECHILD);
2113
2114 f = j->current_file;
2115 if (!f)
2116 return -EADDRNOTAVAIL;
2117
2118 if (f->current_offset <= 0)
2119 return -EADDRNOTAVAIL;
2120
2121 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2122 if (r < 0)
2123 return r;
2124
2125 if (ret_boot_id)
2126 *ret_boot_id = o->entry.boot_id;
2127 else {
2128 r = sd_id128_get_boot(&id);
2129 if (r < 0)
2130 return r;
2131
2132 if (!sd_id128_equal(id, o->entry.boot_id))
2133 return -ESTALE;
2134 }
2135
2136 if (ret)
2137 *ret = le64toh(o->entry.monotonic);
2138
2139 return 0;
2140 }
2141
2142 static bool field_is_valid(const char *field) {
2143 const char *p;
2144
2145 assert(field);
2146
2147 if (isempty(field))
2148 return false;
2149
2150 if (startswith(field, "__"))
2151 return false;
2152
2153 for (p = field; *p; p++) {
2154
2155 if (*p == '_')
2156 continue;
2157
2158 if (*p >= 'A' && *p <= 'Z')
2159 continue;
2160
2161 if (*p >= '0' && *p <= '9')
2162 continue;
2163
2164 return false;
2165 }
2166
2167 return true;
2168 }
2169
2170 _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) {
2171 JournalFile *f;
2172 uint64_t i, n;
2173 size_t field_length;
2174 int r;
2175 Object *o;
2176
2177 assert_return(j, -EINVAL);
2178 assert_return(!journal_pid_changed(j), -ECHILD);
2179 assert_return(field, -EINVAL);
2180 assert_return(data, -EINVAL);
2181 assert_return(size, -EINVAL);
2182 assert_return(field_is_valid(field), -EINVAL);
2183
2184 f = j->current_file;
2185 if (!f)
2186 return -EADDRNOTAVAIL;
2187
2188 if (f->current_offset <= 0)
2189 return -EADDRNOTAVAIL;
2190
2191 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2192 if (r < 0)
2193 return r;
2194
2195 field_length = strlen(field);
2196
2197 n = journal_file_entry_n_items(o);
2198 for (i = 0; i < n; i++) {
2199 uint64_t p, l;
2200 le64_t le_hash;
2201 size_t t;
2202 int compression;
2203
2204 p = le64toh(o->entry.items[i].object_offset);
2205 le_hash = o->entry.items[i].hash;
2206 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
2207 if (r < 0)
2208 return r;
2209
2210 if (le_hash != o->data.hash)
2211 return -EBADMSG;
2212
2213 l = le64toh(o->object.size) - offsetof(Object, data.payload);
2214
2215 compression = o->object.flags & OBJECT_COMPRESSION_MASK;
2216 if (compression) {
2217 #if HAVE_XZ || HAVE_LZ4
2218 r = decompress_startswith(compression,
2219 o->data.payload, l,
2220 &f->compress_buffer, &f->compress_buffer_size,
2221 field, field_length, '=');
2222 if (r < 0)
2223 log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m",
2224 object_compressed_to_string(compression), l, p);
2225 else if (r > 0) {
2226
2227 size_t rsize;
2228
2229 r = decompress_blob(compression,
2230 o->data.payload, l,
2231 &f->compress_buffer, &f->compress_buffer_size, &rsize,
2232 j->data_threshold);
2233 if (r < 0)
2234 return r;
2235
2236 *data = f->compress_buffer;
2237 *size = (size_t) rsize;
2238
2239 return 0;
2240 }
2241 #else
2242 return -EPROTONOSUPPORT;
2243 #endif
2244 } else if (l >= field_length+1 &&
2245 memcmp(o->data.payload, field, field_length) == 0 &&
2246 o->data.payload[field_length] == '=') {
2247
2248 t = (size_t) l;
2249
2250 if ((uint64_t) t != l)
2251 return -E2BIG;
2252
2253 *data = o->data.payload;
2254 *size = t;
2255
2256 return 0;
2257 }
2258
2259 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2260 if (r < 0)
2261 return r;
2262 }
2263
2264 return -ENOENT;
2265 }
2266
2267 static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **data, size_t *size) {
2268 size_t t;
2269 uint64_t l;
2270 int compression;
2271
2272 l = le64toh(o->object.size) - offsetof(Object, data.payload);
2273 t = (size_t) l;
2274
2275 /* We can't read objects larger than 4G on a 32bit machine */
2276 if ((uint64_t) t != l)
2277 return -E2BIG;
2278
2279 compression = o->object.flags & OBJECT_COMPRESSION_MASK;
2280 if (compression) {
2281 #if HAVE_XZ || HAVE_LZ4
2282 size_t rsize;
2283 int r;
2284
2285 r = decompress_blob(compression,
2286 o->data.payload, l, &f->compress_buffer,
2287 &f->compress_buffer_size, &rsize, j->data_threshold);
2288 if (r < 0)
2289 return r;
2290
2291 *data = f->compress_buffer;
2292 *size = (size_t) rsize;
2293 #else
2294 return -EPROTONOSUPPORT;
2295 #endif
2296 } else {
2297 *data = o->data.payload;
2298 *size = t;
2299 }
2300
2301 return 0;
2302 }
2303
2304 _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) {
2305 JournalFile *f;
2306 uint64_t p, n;
2307 le64_t le_hash;
2308 int r;
2309 Object *o;
2310
2311 assert_return(j, -EINVAL);
2312 assert_return(!journal_pid_changed(j), -ECHILD);
2313 assert_return(data, -EINVAL);
2314 assert_return(size, -EINVAL);
2315
2316 f = j->current_file;
2317 if (!f)
2318 return -EADDRNOTAVAIL;
2319
2320 if (f->current_offset <= 0)
2321 return -EADDRNOTAVAIL;
2322
2323 r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
2324 if (r < 0)
2325 return r;
2326
2327 n = journal_file_entry_n_items(o);
2328 if (j->current_field >= n)
2329 return 0;
2330
2331 p = le64toh(o->entry.items[j->current_field].object_offset);
2332 le_hash = o->entry.items[j->current_field].hash;
2333 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
2334 if (r < 0)
2335 return r;
2336
2337 if (le_hash != o->data.hash)
2338 return -EBADMSG;
2339
2340 r = return_data(j, f, o, data, size);
2341 if (r < 0)
2342 return r;
2343
2344 j->current_field++;
2345
2346 return 1;
2347 }
2348
2349 _public_ void sd_journal_restart_data(sd_journal *j) {
2350 if (!j)
2351 return;
2352
2353 j->current_field = 0;
2354 }
2355
2356 static int reiterate_all_paths(sd_journal *j) {
2357 assert(j);
2358
2359 if (j->no_new_files)
2360 return add_current_paths(j);
2361
2362 if (j->flags & SD_JOURNAL_OS_ROOT)
2363 return add_search_paths(j);
2364
2365 if (j->toplevel_fd >= 0)
2366 return add_root_directory(j, NULL, false);
2367
2368 if (j->path)
2369 return add_root_directory(j, j->path, true);
2370
2371 return add_search_paths(j);
2372 }
2373
2374 _public_ int sd_journal_get_fd(sd_journal *j) {
2375 int r;
2376
2377 assert_return(j, -EINVAL);
2378 assert_return(!journal_pid_changed(j), -ECHILD);
2379
2380 if (j->no_inotify)
2381 return -EMEDIUMTYPE;
2382
2383 if (j->inotify_fd >= 0)
2384 return j->inotify_fd;
2385
2386 r = allocate_inotify(j);
2387 if (r < 0)
2388 return r;
2389
2390 log_debug("Reiterating files to get inotify watches established.");
2391
2392 /* Iterate through all dirs again, to add them to the inotify */
2393 r = reiterate_all_paths(j);
2394 if (r < 0)
2395 return r;
2396
2397 return j->inotify_fd;
2398 }
2399
2400 _public_ int sd_journal_get_events(sd_journal *j) {
2401 int fd;
2402
2403 assert_return(j, -EINVAL);
2404 assert_return(!journal_pid_changed(j), -ECHILD);
2405
2406 fd = sd_journal_get_fd(j);
2407 if (fd < 0)
2408 return fd;
2409
2410 return POLLIN;
2411 }
2412
2413 _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
2414 int fd;
2415
2416 assert_return(j, -EINVAL);
2417 assert_return(!journal_pid_changed(j), -ECHILD);
2418 assert_return(timeout_usec, -EINVAL);
2419
2420 fd = sd_journal_get_fd(j);
2421 if (fd < 0)
2422 return fd;
2423
2424 if (!j->on_network) {
2425 *timeout_usec = (uint64_t) -1;
2426 return 0;
2427 }
2428
2429 /* If we are on the network we need to regularly check for
2430 * changes manually */
2431
2432 *timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC;
2433 return 1;
2434 }
2435
2436 static void process_q_overflow(sd_journal *j) {
2437 JournalFile *f;
2438 Directory *m;
2439 Iterator i;
2440
2441 assert(j);
2442
2443 /* When the inotify queue overruns we need to enumerate and re-validate all journal files to bring our list
2444 * back in sync with what's on disk. For this we pick a new generation counter value. It'll be assigned to all
2445 * journal files we encounter. All journal files and all directories that don't carry it after reenumeration
2446 * are subject for unloading. */
2447
2448 log_debug("Inotify queue overrun, reiterating everything.");
2449
2450 j->generation++;
2451 (void) reiterate_all_paths(j);
2452
2453 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2454
2455 if (f->last_seen_generation == j->generation)
2456 continue;
2457
2458 log_debug("File '%s' hasn't been seen in this enumeration, removing.", f->path);
2459 remove_file_real(j, f);
2460 }
2461
2462 HASHMAP_FOREACH(m, j->directories_by_path, i) {
2463
2464 if (m->last_seen_generation == j->generation)
2465 continue;
2466
2467 if (m->is_root) /* Never GC root directories */
2468 continue;
2469
2470 log_debug("Directory '%s' hasn't been seen in this enumeration, removing.", f->path);
2471 remove_directory(j, m);
2472 }
2473
2474 log_debug("Reiteration complete.");
2475 }
2476
2477 static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
2478 Directory *d;
2479
2480 assert(j);
2481 assert(e);
2482
2483 if (e->mask & IN_Q_OVERFLOW) {
2484 process_q_overflow(j);
2485 return;
2486 }
2487
2488 /* Is this a subdirectory we watch? */
2489 d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd));
2490 if (d) {
2491 if (!(e->mask & IN_ISDIR) && e->len > 0 &&
2492 (endswith(e->name, ".journal") ||
2493 endswith(e->name, ".journal~"))) {
2494
2495 /* Event for a journal file */
2496
2497 if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
2498 (void) add_file(j, d->path, e->name);
2499 else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT))
2500 remove_file(j, d->path, e->name);
2501
2502 } else if (!d->is_root && e->len == 0) {
2503
2504 /* Event for a subdirectory */
2505
2506 if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT))
2507 remove_directory(j, d);
2508
2509 } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && id128_is_valid(e->name)) {
2510
2511 /* Event for root directory */
2512
2513 if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
2514 (void) add_directory(j, d->path, e->name);
2515 }
2516
2517 return;
2518 }
2519
2520 if (e->mask & IN_IGNORED)
2521 return;
2522
2523 log_debug("Unexpected inotify event.");
2524 }
2525
2526 static int determine_change(sd_journal *j) {
2527 bool b;
2528
2529 assert(j);
2530
2531 b = j->current_invalidate_counter != j->last_invalidate_counter;
2532 j->last_invalidate_counter = j->current_invalidate_counter;
2533
2534 return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND;
2535 }
2536
2537 _public_ int sd_journal_process(sd_journal *j) {
2538 bool got_something = false;
2539
2540 assert_return(j, -EINVAL);
2541 assert_return(!journal_pid_changed(j), -ECHILD);
2542
2543 if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */
2544 return 0;
2545
2546 j->last_process_usec = now(CLOCK_MONOTONIC);
2547 j->last_invalidate_counter = j->current_invalidate_counter;
2548
2549 for (;;) {
2550 union inotify_event_buffer buffer;
2551 struct inotify_event *e;
2552 ssize_t l;
2553
2554 l = read(j->inotify_fd, &buffer, sizeof(buffer));
2555 if (l < 0) {
2556 if (IN_SET(errno, EAGAIN, EINTR))
2557 return got_something ? determine_change(j) : SD_JOURNAL_NOP;
2558
2559 return -errno;
2560 }
2561
2562 got_something = true;
2563
2564 FOREACH_INOTIFY_EVENT(e, buffer, l)
2565 process_inotify_event(j, e);
2566 }
2567 }
2568
2569 _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
2570 int r;
2571 uint64_t t;
2572
2573 assert_return(j, -EINVAL);
2574 assert_return(!journal_pid_changed(j), -ECHILD);
2575
2576 if (j->inotify_fd < 0) {
2577
2578 /* This is the first invocation, hence create the
2579 * inotify watch */
2580 r = sd_journal_get_fd(j);
2581 if (r < 0)
2582 return r;
2583
2584 /* The journal might have changed since the context
2585 * object was created and we weren't watching before,
2586 * hence don't wait for anything, and return
2587 * immediately. */
2588 return determine_change(j);
2589 }
2590
2591 r = sd_journal_get_timeout(j, &t);
2592 if (r < 0)
2593 return r;
2594
2595 if (t != (uint64_t) -1) {
2596 usec_t n;
2597
2598 n = now(CLOCK_MONOTONIC);
2599 t = t > n ? t - n : 0;
2600
2601 if (timeout_usec == (uint64_t) -1 || timeout_usec > t)
2602 timeout_usec = t;
2603 }
2604
2605 do {
2606 r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec);
2607 } while (r == -EINTR);
2608
2609 if (r < 0)
2610 return r;
2611
2612 return sd_journal_process(j);
2613 }
2614
2615 _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) {
2616 Iterator i;
2617 JournalFile *f;
2618 bool first = true;
2619 uint64_t fmin = 0, tmax = 0;
2620 int r;
2621
2622 assert_return(j, -EINVAL);
2623 assert_return(!journal_pid_changed(j), -ECHILD);
2624 assert_return(from || to, -EINVAL);
2625 assert_return(from != to, -EINVAL);
2626
2627 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2628 usec_t fr, t;
2629
2630 r = journal_file_get_cutoff_realtime_usec(f, &fr, &t);
2631 if (r == -ENOENT)
2632 continue;
2633 if (r < 0)
2634 return r;
2635 if (r == 0)
2636 continue;
2637
2638 if (first) {
2639 fmin = fr;
2640 tmax = t;
2641 first = false;
2642 } else {
2643 fmin = MIN(fr, fmin);
2644 tmax = MAX(t, tmax);
2645 }
2646 }
2647
2648 if (from)
2649 *from = fmin;
2650 if (to)
2651 *to = tmax;
2652
2653 return first ? 0 : 1;
2654 }
2655
2656 _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) {
2657 Iterator i;
2658 JournalFile *f;
2659 bool found = false;
2660 int r;
2661
2662 assert_return(j, -EINVAL);
2663 assert_return(!journal_pid_changed(j), -ECHILD);
2664 assert_return(from || to, -EINVAL);
2665 assert_return(from != to, -EINVAL);
2666
2667 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2668 usec_t fr, t;
2669
2670 r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t);
2671 if (r == -ENOENT)
2672 continue;
2673 if (r < 0)
2674 return r;
2675 if (r == 0)
2676 continue;
2677
2678 if (found) {
2679 if (from)
2680 *from = MIN(fr, *from);
2681 if (to)
2682 *to = MAX(t, *to);
2683 } else {
2684 if (from)
2685 *from = fr;
2686 if (to)
2687 *to = t;
2688 found = true;
2689 }
2690 }
2691
2692 return found;
2693 }
2694
2695 void journal_print_header(sd_journal *j) {
2696 Iterator i;
2697 JournalFile *f;
2698 bool newline = false;
2699
2700 assert(j);
2701
2702 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2703 if (newline)
2704 putchar('\n');
2705 else
2706 newline = true;
2707
2708 journal_file_print_header(f);
2709 }
2710 }
2711
2712 _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
2713 Iterator i;
2714 JournalFile *f;
2715 uint64_t sum = 0;
2716
2717 assert_return(j, -EINVAL);
2718 assert_return(!journal_pid_changed(j), -ECHILD);
2719 assert_return(bytes, -EINVAL);
2720
2721 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
2722 struct stat st;
2723
2724 if (fstat(f->fd, &st) < 0)
2725 return -errno;
2726
2727 sum += (uint64_t) st.st_blocks * 512ULL;
2728 }
2729
2730 *bytes = sum;
2731 return 0;
2732 }
2733
2734 _public_ int sd_journal_query_unique(sd_journal *j, const char *field) {
2735 char *f;
2736
2737 assert_return(j, -EINVAL);
2738 assert_return(!journal_pid_changed(j), -ECHILD);
2739 assert_return(!isempty(field), -EINVAL);
2740 assert_return(field_is_valid(field), -EINVAL);
2741
2742 f = strdup(field);
2743 if (!f)
2744 return -ENOMEM;
2745
2746 free(j->unique_field);
2747 j->unique_field = f;
2748 j->unique_file = NULL;
2749 j->unique_offset = 0;
2750 j->unique_file_lost = false;
2751
2752 return 0;
2753 }
2754
2755 _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) {
2756 size_t k;
2757
2758 assert_return(j, -EINVAL);
2759 assert_return(!journal_pid_changed(j), -ECHILD);
2760 assert_return(data, -EINVAL);
2761 assert_return(l, -EINVAL);
2762 assert_return(j->unique_field, -EINVAL);
2763
2764 k = strlen(j->unique_field);
2765
2766 if (!j->unique_file) {
2767 if (j->unique_file_lost)
2768 return 0;
2769
2770 j->unique_file = ordered_hashmap_first(j->files);
2771 if (!j->unique_file)
2772 return 0;
2773
2774 j->unique_offset = 0;
2775 }
2776
2777 for (;;) {
2778 JournalFile *of;
2779 Iterator i;
2780 Object *o;
2781 const void *odata;
2782 size_t ol;
2783 bool found;
2784 int r;
2785
2786 /* Proceed to next data object in the field's linked list */
2787 if (j->unique_offset == 0) {
2788 r = journal_file_find_field_object(j->unique_file, j->unique_field, k, &o, NULL);
2789 if (r < 0)
2790 return r;
2791
2792 j->unique_offset = r > 0 ? le64toh(o->field.head_data_offset) : 0;
2793 } else {
2794 r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o);
2795 if (r < 0)
2796 return r;
2797
2798 j->unique_offset = le64toh(o->data.next_field_offset);
2799 }
2800
2801 /* We reached the end of the list? Then start again, with the next file */
2802 if (j->unique_offset == 0) {
2803 j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
2804 if (!j->unique_file)
2805 return 0;
2806
2807 continue;
2808 }
2809
2810 /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED
2811 * instead, so that we can look at this data object at the same
2812 * time as one on another file */
2813 r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o);
2814 if (r < 0)
2815 return r;
2816
2817 /* Let's do the type check by hand, since we used 0 context above. */
2818 if (o->object.type != OBJECT_DATA) {
2819 log_debug("%s:offset " OFSfmt ": object has type %d, expected %d",
2820 j->unique_file->path, j->unique_offset,
2821 o->object.type, OBJECT_DATA);
2822 return -EBADMSG;
2823 }
2824
2825 r = return_data(j, j->unique_file, o, &odata, &ol);
2826 if (r < 0)
2827 return r;
2828
2829 /* Check if we have at least the field name and "=". */
2830 if (ol <= k) {
2831 log_debug("%s:offset " OFSfmt ": object has size %zu, expected at least %zu",
2832 j->unique_file->path, j->unique_offset,
2833 ol, k + 1);
2834 return -EBADMSG;
2835 }
2836
2837 if (memcmp(odata, j->unique_field, k) || ((const char*) odata)[k] != '=') {
2838 log_debug("%s:offset " OFSfmt ": object does not start with \"%s=\"",
2839 j->unique_file->path, j->unique_offset,
2840 j->unique_field);
2841 return -EBADMSG;
2842 }
2843
2844 /* OK, now let's see if we already returned this data
2845 * object by checking if it exists in the earlier
2846 * traversed files. */
2847 found = false;
2848 ORDERED_HASHMAP_FOREACH(of, j->files, i) {
2849 if (of == j->unique_file)
2850 break;
2851
2852 /* Skip this file it didn't have any fields indexed */
2853 if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0)
2854 continue;
2855
2856 r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), NULL, NULL);
2857 if (r < 0)
2858 return r;
2859 if (r > 0) {
2860 found = true;
2861 break;
2862 }
2863 }
2864
2865 if (found)
2866 continue;
2867
2868 r = return_data(j, j->unique_file, o, data, l);
2869 if (r < 0)
2870 return r;
2871
2872 return 1;
2873 }
2874 }
2875
2876 _public_ void sd_journal_restart_unique(sd_journal *j) {
2877 if (!j)
2878 return;
2879
2880 j->unique_file = NULL;
2881 j->unique_offset = 0;
2882 j->unique_file_lost = false;
2883 }
2884
2885 _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) {
2886 int r;
2887
2888 assert_return(j, -EINVAL);
2889 assert_return(!journal_pid_changed(j), -ECHILD);
2890 assert_return(field, -EINVAL);
2891
2892 if (!j->fields_file) {
2893 if (j->fields_file_lost)
2894 return 0;
2895
2896 j->fields_file = ordered_hashmap_first(j->files);
2897 if (!j->fields_file)
2898 return 0;
2899
2900 j->fields_hash_table_index = 0;
2901 j->fields_offset = 0;
2902 }
2903
2904 for (;;) {
2905 JournalFile *f, *of;
2906 Iterator i;
2907 uint64_t m;
2908 Object *o;
2909 size_t sz;
2910 bool found;
2911
2912 f = j->fields_file;
2913
2914 if (j->fields_offset == 0) {
2915 bool eof = false;
2916
2917 /* We are not yet positioned at any field. Let's pick the first one */
2918 r = journal_file_map_field_hash_table(f);
2919 if (r < 0)
2920 return r;
2921
2922 m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
2923 for (;;) {
2924 if (j->fields_hash_table_index >= m) {
2925 /* Reached the end of the hash table, go to the next file. */
2926 eof = true;
2927 break;
2928 }
2929
2930 j->fields_offset = le64toh(f->field_hash_table[j->fields_hash_table_index].head_hash_offset);
2931
2932 if (j->fields_offset != 0)
2933 break;
2934
2935 /* Empty hash table bucket, go to next one */
2936 j->fields_hash_table_index++;
2937 }
2938
2939 if (eof) {
2940 /* Proceed with next file */
2941 j->fields_file = ordered_hashmap_next(j->files, f->path);
2942 if (!j->fields_file) {
2943 *field = NULL;
2944 return 0;
2945 }
2946
2947 j->fields_offset = 0;
2948 j->fields_hash_table_index = 0;
2949 continue;
2950 }
2951
2952 } else {
2953 /* We are already positioned at a field. If so, let's figure out the next field from it */
2954
2955 r = journal_file_move_to_object(f, OBJECT_FIELD, j->fields_offset, &o);
2956 if (r < 0)
2957 return r;
2958
2959 j->fields_offset = le64toh(o->field.next_hash_offset);
2960 if (j->fields_offset == 0) {
2961 /* Reached the end of the hash table chain */
2962 j->fields_hash_table_index++;
2963 continue;
2964 }
2965 }
2966
2967 /* We use OBJECT_UNUSED here, so that the iterator below doesn't remove our mmap window */
2968 r = journal_file_move_to_object(f, OBJECT_UNUSED, j->fields_offset, &o);
2969 if (r < 0)
2970 return r;
2971
2972 /* Because we used OBJECT_UNUSED above, we need to do our type check manually */
2973 if (o->object.type != OBJECT_FIELD) {
2974 log_debug("%s:offset " OFSfmt ": object has type %i, expected %i", f->path, j->fields_offset, o->object.type, OBJECT_FIELD);
2975 return -EBADMSG;
2976 }
2977
2978 sz = le64toh(o->object.size) - offsetof(Object, field.payload);
2979
2980 /* Let's see if we already returned this field name before. */
2981 found = false;
2982 ORDERED_HASHMAP_FOREACH(of, j->files, i) {
2983 if (of == f)
2984 break;
2985
2986 /* Skip this file it didn't have any fields indexed */
2987 if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0)
2988 continue;
2989
2990 r = journal_file_find_field_object_with_hash(of, o->field.payload, sz, le64toh(o->field.hash), NULL, NULL);
2991 if (r < 0)
2992 return r;
2993 if (r > 0) {
2994 found = true;
2995 break;
2996 }
2997 }
2998
2999 if (found)
3000 continue;
3001
3002 /* Check if this is really a valid string containing no NUL byte */
3003 if (memchr(o->field.payload, 0, sz))
3004 return -EBADMSG;
3005
3006 if (sz > j->data_threshold)
3007 sz = j->data_threshold;
3008
3009 if (!GREEDY_REALLOC(j->fields_buffer, j->fields_buffer_allocated, sz + 1))
3010 return -ENOMEM;
3011
3012 memcpy(j->fields_buffer, o->field.payload, sz);
3013 j->fields_buffer[sz] = 0;
3014
3015 if (!field_is_valid(j->fields_buffer))
3016 return -EBADMSG;
3017
3018 *field = j->fields_buffer;
3019 return 1;
3020 }
3021 }
3022
3023 _public_ void sd_journal_restart_fields(sd_journal *j) {
3024 if (!j)
3025 return;
3026
3027 j->fields_file = NULL;
3028 j->fields_hash_table_index = 0;
3029 j->fields_offset = 0;
3030 j->fields_file_lost = false;
3031 }
3032
3033 _public_ int sd_journal_reliable_fd(sd_journal *j) {
3034 assert_return(j, -EINVAL);
3035 assert_return(!journal_pid_changed(j), -ECHILD);
3036
3037 return !j->on_network;
3038 }
3039
3040 static char *lookup_field(const char *field, void *userdata) {
3041 sd_journal *j = userdata;
3042 const void *data;
3043 size_t size, d;
3044 int r;
3045
3046 assert(field);
3047 assert(j);
3048
3049 r = sd_journal_get_data(j, field, &data, &size);
3050 if (r < 0 ||
3051 size > REPLACE_VAR_MAX)
3052 return strdup(field);
3053
3054 d = strlen(field) + 1;
3055
3056 return strndup((const char*) data + d, size - d);
3057 }
3058
3059 _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) {
3060 const void *data;
3061 size_t size;
3062 sd_id128_t id;
3063 _cleanup_free_ char *text = NULL, *cid = NULL;
3064 char *t;
3065 int r;
3066
3067 assert_return(j, -EINVAL);
3068 assert_return(!journal_pid_changed(j), -ECHILD);
3069 assert_return(ret, -EINVAL);
3070
3071 r = sd_journal_get_data(j, "MESSAGE_ID", &data, &size);
3072 if (r < 0)
3073 return r;
3074
3075 cid = strndup((const char*) data + 11, size - 11);
3076 if (!cid)
3077 return -ENOMEM;
3078
3079 r = sd_id128_from_string(cid, &id);
3080 if (r < 0)
3081 return r;
3082
3083 r = catalog_get(CATALOG_DATABASE, id, &text);
3084 if (r < 0)
3085 return r;
3086
3087 t = replace_var(text, lookup_field, j);
3088 if (!t)
3089 return -ENOMEM;
3090
3091 *ret = t;
3092 return 0;
3093 }
3094
3095 _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) {
3096 assert_return(ret, -EINVAL);
3097
3098 return catalog_get(CATALOG_DATABASE, id, ret);
3099 }
3100
3101 _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {
3102 assert_return(j, -EINVAL);
3103 assert_return(!journal_pid_changed(j), -ECHILD);
3104
3105 j->data_threshold = sz;
3106 return 0;
3107 }
3108
3109 _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) {
3110 assert_return(j, -EINVAL);
3111 assert_return(!journal_pid_changed(j), -ECHILD);
3112 assert_return(sz, -EINVAL);
3113
3114 *sz = j->data_threshold;
3115 return 0;
3116 }
3117
3118 _public_ int sd_journal_has_runtime_files(sd_journal *j) {
3119 assert_return(j, -EINVAL);
3120
3121 return j->has_runtime_files;
3122 }
3123
3124 _public_ int sd_journal_has_persistent_files(sd_journal *j) {
3125 assert_return(j, -EINVAL);
3126
3127 return j->has_persistent_files;
3128 }