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