]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl.c
util-lib: split out IO related calls to io-util.[ch]
[thirdparty/systemd.git] / src / journal / journalctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <fnmatch.h>
25 #include <getopt.h>
26 #include <linux/fs.h>
27 #include <locale.h>
28 #include <poll.h>
29 #include <signal.h>
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/inotify.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37
38 #include "sd-bus.h"
39 #include "sd-journal.h"
40
41 #include "acl-util.h"
42 #include "bus-error.h"
43 #include "bus-util.h"
44 #include "catalog.h"
45 #include "fd-util.h"
46 #include "fileio.h"
47 #include "fsprg.h"
48 #include "hostname-util.h"
49 #include "io-util.h"
50 #include "journal-def.h"
51 #include "journal-internal.h"
52 #include "journal-qrcode.h"
53 #include "journal-vacuum.h"
54 #include "journal-verify.h"
55 #include "log.h"
56 #include "logs-show.h"
57 #include "mkdir.h"
58 #include "pager.h"
59 #include "path-util.h"
60 #include "set.h"
61 #include "sigbus.h"
62 #include "strv.h"
63 #include "terminal-util.h"
64 #include "unit-name.h"
65
66 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
67
68 enum {
69 /* Special values for arg_lines */
70 ARG_LINES_DEFAULT = -2,
71 ARG_LINES_ALL = -1,
72 };
73
74 static OutputMode arg_output = OUTPUT_SHORT;
75 static bool arg_utc = false;
76 static bool arg_pager_end = false;
77 static bool arg_follow = false;
78 static bool arg_full = true;
79 static bool arg_all = false;
80 static bool arg_no_pager = false;
81 static int arg_lines = ARG_LINES_DEFAULT;
82 static bool arg_no_tail = false;
83 static bool arg_quiet = false;
84 static bool arg_merge = false;
85 static bool arg_boot = false;
86 static sd_id128_t arg_boot_id = {};
87 static int arg_boot_offset = 0;
88 static bool arg_dmesg = false;
89 static const char *arg_cursor = NULL;
90 static const char *arg_after_cursor = NULL;
91 static bool arg_show_cursor = false;
92 static const char *arg_directory = NULL;
93 static char **arg_file = NULL;
94 static int arg_priorities = 0xFF;
95 static const char *arg_verify_key = NULL;
96 #ifdef HAVE_GCRYPT
97 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
98 static bool arg_force = false;
99 #endif
100 static usec_t arg_since, arg_until;
101 static bool arg_since_set = false, arg_until_set = false;
102 static char **arg_syslog_identifier = NULL;
103 static char **arg_system_units = NULL;
104 static char **arg_user_units = NULL;
105 static const char *arg_field = NULL;
106 static bool arg_catalog = false;
107 static bool arg_reverse = false;
108 static int arg_journal_type = 0;
109 static char *arg_root = NULL;
110 static const char *arg_machine = NULL;
111 static uint64_t arg_vacuum_size = 0;
112 static uint64_t arg_vacuum_n_files = 0;
113 static usec_t arg_vacuum_time = 0;
114
115 static enum {
116 ACTION_SHOW,
117 ACTION_NEW_ID128,
118 ACTION_PRINT_HEADER,
119 ACTION_SETUP_KEYS,
120 ACTION_VERIFY,
121 ACTION_DISK_USAGE,
122 ACTION_LIST_CATALOG,
123 ACTION_DUMP_CATALOG,
124 ACTION_UPDATE_CATALOG,
125 ACTION_LIST_BOOTS,
126 ACTION_FLUSH,
127 ACTION_ROTATE,
128 ACTION_VACUUM,
129 } arg_action = ACTION_SHOW;
130
131 typedef struct BootId {
132 sd_id128_t id;
133 uint64_t first;
134 uint64_t last;
135 LIST_FIELDS(struct BootId, boot_list);
136 } BootId;
137
138 static void pager_open_if_enabled(void) {
139
140 if (arg_no_pager)
141 return;
142
143 pager_open(arg_pager_end);
144 }
145
146 static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) {
147
148 if (arg_utc)
149 return format_timestamp_utc(buf, l, t);
150
151 return format_timestamp(buf, l, t);
152 }
153
154 static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) {
155 sd_id128_t id = SD_ID128_NULL;
156 int off = 0, r;
157
158 if (strlen(x) >= 32) {
159 char *t;
160
161 t = strndupa(x, 32);
162 r = sd_id128_from_string(t, &id);
163 if (r >= 0)
164 x += 32;
165
166 if (*x != '-' && *x != '+' && *x != 0)
167 return -EINVAL;
168
169 if (*x != 0) {
170 r = safe_atoi(x, &off);
171 if (r < 0)
172 return r;
173 }
174 } else {
175 r = safe_atoi(x, &off);
176 if (r < 0)
177 return r;
178 }
179
180 if (boot_id)
181 *boot_id = id;
182
183 if (offset)
184 *offset = off;
185
186 return 0;
187 }
188
189 static void help(void) {
190
191 pager_open_if_enabled();
192
193 printf("%s [OPTIONS...] [MATCHES...]\n\n"
194 "Query the journal.\n\n"
195 "Flags:\n"
196 " --system Show the system journal\n"
197 " --user Show the user journal for the current user\n"
198 " -M --machine=CONTAINER Operate on local container\n"
199 " -S --since=DATE Show entries not older than the specified date\n"
200 " -U --until=DATE Show entries not newer than the specified date\n"
201 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
202 " --after-cursor=CURSOR Show entries after the specified cursor\n"
203 " --show-cursor Print the cursor after all the entries\n"
204 " -b --boot[=ID] Show current boot or the specified boot\n"
205 " --list-boots Show terse information about recorded boots\n"
206 " -k --dmesg Show kernel message log from the current boot\n"
207 " -u --unit=UNIT Show logs from the specified unit\n"
208 " --user-unit=UNIT Show logs from the specified user unit\n"
209 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
210 " -p --priority=RANGE Show entries with the specified priority\n"
211 " -e --pager-end Immediately jump to the end in the pager\n"
212 " -f --follow Follow the journal\n"
213 " -n --lines[=INTEGER] Number of journal entries to show\n"
214 " --no-tail Show all lines, even in follow mode\n"
215 " -r --reverse Show the newest entries first\n"
216 " -o --output=STRING Change journal output mode (short, short-iso,\n"
217 " short-precise, short-monotonic, verbose,\n"
218 " export, json, json-pretty, json-sse, cat)\n"
219 " --utc Express time in Coordinated Universal Time (UTC)\n"
220 " -x --catalog Add message explanations where available\n"
221 " --no-full Ellipsize fields\n"
222 " -a --all Show all fields, including long and unprintable\n"
223 " -q --quiet Do not show info messages and privilege warning\n"
224 " --no-pager Do not pipe output into a pager\n"
225 " -m --merge Show entries from all available journals\n"
226 " -D --directory=PATH Show journal files from directory\n"
227 " --file=PATH Show journal file\n"
228 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
229 #ifdef HAVE_GCRYPT
230 " --interval=TIME Time interval for changing the FSS sealing key\n"
231 " --verify-key=KEY Specify FSS verification key\n"
232 " --force Override of the FSS key pair with --setup-keys\n"
233 #endif
234 "\nCommands:\n"
235 " -h --help Show this help text\n"
236 " --version Show package version\n"
237 " -F --field=FIELD List all values that a specified field takes\n"
238 " --new-id128 Generate a new 128-bit ID\n"
239 " --disk-usage Show total disk usage of all journal files\n"
240 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
241 " --vacuum-files=INT Leave only the specified number of journal files\n"
242 " --vacuum-time=TIME Remove journal files older than specified time\n"
243 " --flush Flush all journal data from /run into /var\n"
244 " --rotate Request immediate rotation of the journal files\n"
245 " --header Show journal header information\n"
246 " --list-catalog Show all message IDs in the catalog\n"
247 " --dump-catalog Show entries in the message catalog\n"
248 " --update-catalog Update the message catalog database\n"
249 #ifdef HAVE_GCRYPT
250 " --setup-keys Generate a new FSS key pair\n"
251 " --verify Verify journal file consistency\n"
252 #endif
253 , program_invocation_short_name);
254 }
255
256 static int parse_argv(int argc, char *argv[]) {
257
258 enum {
259 ARG_VERSION = 0x100,
260 ARG_NO_PAGER,
261 ARG_NO_FULL,
262 ARG_NO_TAIL,
263 ARG_NEW_ID128,
264 ARG_LIST_BOOTS,
265 ARG_USER,
266 ARG_SYSTEM,
267 ARG_ROOT,
268 ARG_HEADER,
269 ARG_SETUP_KEYS,
270 ARG_FILE,
271 ARG_INTERVAL,
272 ARG_VERIFY,
273 ARG_VERIFY_KEY,
274 ARG_DISK_USAGE,
275 ARG_AFTER_CURSOR,
276 ARG_SHOW_CURSOR,
277 ARG_USER_UNIT,
278 ARG_LIST_CATALOG,
279 ARG_DUMP_CATALOG,
280 ARG_UPDATE_CATALOG,
281 ARG_FORCE,
282 ARG_UTC,
283 ARG_FLUSH,
284 ARG_ROTATE,
285 ARG_VACUUM_SIZE,
286 ARG_VACUUM_FILES,
287 ARG_VACUUM_TIME,
288 };
289
290 static const struct option options[] = {
291 { "help", no_argument, NULL, 'h' },
292 { "version" , no_argument, NULL, ARG_VERSION },
293 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
294 { "pager-end", no_argument, NULL, 'e' },
295 { "follow", no_argument, NULL, 'f' },
296 { "force", no_argument, NULL, ARG_FORCE },
297 { "output", required_argument, NULL, 'o' },
298 { "all", no_argument, NULL, 'a' },
299 { "full", no_argument, NULL, 'l' },
300 { "no-full", no_argument, NULL, ARG_NO_FULL },
301 { "lines", optional_argument, NULL, 'n' },
302 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
303 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
304 { "quiet", no_argument, NULL, 'q' },
305 { "merge", no_argument, NULL, 'm' },
306 { "boot", optional_argument, NULL, 'b' },
307 { "list-boots", no_argument, NULL, ARG_LIST_BOOTS },
308 { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */
309 { "dmesg", no_argument, NULL, 'k' },
310 { "system", no_argument, NULL, ARG_SYSTEM },
311 { "user", no_argument, NULL, ARG_USER },
312 { "directory", required_argument, NULL, 'D' },
313 { "file", required_argument, NULL, ARG_FILE },
314 { "root", required_argument, NULL, ARG_ROOT },
315 { "header", no_argument, NULL, ARG_HEADER },
316 { "identifier", required_argument, NULL, 't' },
317 { "priority", required_argument, NULL, 'p' },
318 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
319 { "interval", required_argument, NULL, ARG_INTERVAL },
320 { "verify", no_argument, NULL, ARG_VERIFY },
321 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
322 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
323 { "cursor", required_argument, NULL, 'c' },
324 { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
325 { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
326 { "since", required_argument, NULL, 'S' },
327 { "until", required_argument, NULL, 'U' },
328 { "unit", required_argument, NULL, 'u' },
329 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
330 { "field", required_argument, NULL, 'F' },
331 { "catalog", no_argument, NULL, 'x' },
332 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
333 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
334 { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
335 { "reverse", no_argument, NULL, 'r' },
336 { "machine", required_argument, NULL, 'M' },
337 { "utc", no_argument, NULL, ARG_UTC },
338 { "flush", no_argument, NULL, ARG_FLUSH },
339 { "rotate", no_argument, NULL, ARG_ROTATE },
340 { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
341 { "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES },
342 { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME },
343 {}
344 };
345
346 int c, r;
347
348 assert(argc >= 0);
349 assert(argv);
350
351 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:F:xrM:", options, NULL)) >= 0)
352
353 switch (c) {
354
355 case 'h':
356 help();
357 return 0;
358
359 case ARG_VERSION:
360 return version();
361
362 case ARG_NO_PAGER:
363 arg_no_pager = true;
364 break;
365
366 case 'e':
367 arg_pager_end = true;
368
369 if (arg_lines == ARG_LINES_DEFAULT)
370 arg_lines = 1000;
371
372 break;
373
374 case 'f':
375 arg_follow = true;
376 break;
377
378 case 'o':
379 arg_output = output_mode_from_string(optarg);
380 if (arg_output < 0) {
381 log_error("Unknown output format '%s'.", optarg);
382 return -EINVAL;
383 }
384
385 if (arg_output == OUTPUT_EXPORT ||
386 arg_output == OUTPUT_JSON ||
387 arg_output == OUTPUT_JSON_PRETTY ||
388 arg_output == OUTPUT_JSON_SSE ||
389 arg_output == OUTPUT_CAT)
390 arg_quiet = true;
391
392 break;
393
394 case 'l':
395 arg_full = true;
396 break;
397
398 case ARG_NO_FULL:
399 arg_full = false;
400 break;
401
402 case 'a':
403 arg_all = true;
404 break;
405
406 case 'n':
407 if (optarg) {
408 if (streq(optarg, "all"))
409 arg_lines = ARG_LINES_ALL;
410 else {
411 r = safe_atoi(optarg, &arg_lines);
412 if (r < 0 || arg_lines < 0) {
413 log_error("Failed to parse lines '%s'", optarg);
414 return -EINVAL;
415 }
416 }
417 } else {
418 arg_lines = 10;
419
420 /* Hmm, no argument? Maybe the next
421 * word on the command line is
422 * supposed to be the argument? Let's
423 * see if there is one, and is
424 * parsable. */
425 if (optind < argc) {
426 int n;
427 if (streq(argv[optind], "all")) {
428 arg_lines = ARG_LINES_ALL;
429 optind++;
430 } else if (safe_atoi(argv[optind], &n) >= 0 && n >= 0) {
431 arg_lines = n;
432 optind++;
433 }
434 }
435 }
436
437 break;
438
439 case ARG_NO_TAIL:
440 arg_no_tail = true;
441 break;
442
443 case ARG_NEW_ID128:
444 arg_action = ACTION_NEW_ID128;
445 break;
446
447 case 'q':
448 arg_quiet = true;
449 break;
450
451 case 'm':
452 arg_merge = true;
453 break;
454
455 case 'b':
456 arg_boot = true;
457
458 if (optarg) {
459 r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
460 if (r < 0) {
461 log_error("Failed to parse boot descriptor '%s'", optarg);
462 return -EINVAL;
463 }
464 } else {
465
466 /* Hmm, no argument? Maybe the next
467 * word on the command line is
468 * supposed to be the argument? Let's
469 * see if there is one and is parsable
470 * as a boot descriptor... */
471
472 if (optind < argc &&
473 parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset) >= 0)
474 optind++;
475 }
476
477 break;
478
479 case ARG_LIST_BOOTS:
480 arg_action = ACTION_LIST_BOOTS;
481 break;
482
483 case 'k':
484 arg_boot = arg_dmesg = true;
485 break;
486
487 case ARG_SYSTEM:
488 arg_journal_type |= SD_JOURNAL_SYSTEM;
489 break;
490
491 case ARG_USER:
492 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
493 break;
494
495 case 'M':
496 arg_machine = optarg;
497 break;
498
499 case 'D':
500 arg_directory = optarg;
501 break;
502
503 case ARG_FILE:
504 r = glob_extend(&arg_file, optarg);
505 if (r < 0)
506 return log_error_errno(r, "Failed to add paths: %m");
507 break;
508
509 case ARG_ROOT:
510 r = parse_path_argument_and_warn(optarg, true, &arg_root);
511 if (r < 0)
512 return r;
513 break;
514
515 case 'c':
516 arg_cursor = optarg;
517 break;
518
519 case ARG_AFTER_CURSOR:
520 arg_after_cursor = optarg;
521 break;
522
523 case ARG_SHOW_CURSOR:
524 arg_show_cursor = true;
525 break;
526
527 case ARG_HEADER:
528 arg_action = ACTION_PRINT_HEADER;
529 break;
530
531 case ARG_VERIFY:
532 arg_action = ACTION_VERIFY;
533 break;
534
535 case ARG_DISK_USAGE:
536 arg_action = ACTION_DISK_USAGE;
537 break;
538
539 case ARG_VACUUM_SIZE:
540 r = parse_size(optarg, 1024, &arg_vacuum_size);
541 if (r < 0) {
542 log_error("Failed to parse vacuum size: %s", optarg);
543 return r;
544 }
545
546 arg_action = ACTION_VACUUM;
547 break;
548
549 case ARG_VACUUM_FILES:
550 r = safe_atou64(optarg, &arg_vacuum_n_files);
551 if (r < 0) {
552 log_error("Failed to parse vacuum files: %s", optarg);
553 return r;
554 }
555
556 arg_action = ACTION_VACUUM;
557 break;
558
559 case ARG_VACUUM_TIME:
560 r = parse_sec(optarg, &arg_vacuum_time);
561 if (r < 0) {
562 log_error("Failed to parse vacuum time: %s", optarg);
563 return r;
564 }
565
566 arg_action = ACTION_VACUUM;
567 break;
568
569 #ifdef HAVE_GCRYPT
570 case ARG_FORCE:
571 arg_force = true;
572 break;
573
574 case ARG_SETUP_KEYS:
575 arg_action = ACTION_SETUP_KEYS;
576 break;
577
578
579 case ARG_VERIFY_KEY:
580 arg_action = ACTION_VERIFY;
581 arg_verify_key = optarg;
582 arg_merge = false;
583 break;
584
585 case ARG_INTERVAL:
586 r = parse_sec(optarg, &arg_interval);
587 if (r < 0 || arg_interval <= 0) {
588 log_error("Failed to parse sealing key change interval: %s", optarg);
589 return -EINVAL;
590 }
591 break;
592 #else
593 case ARG_SETUP_KEYS:
594 case ARG_VERIFY_KEY:
595 case ARG_INTERVAL:
596 case ARG_FORCE:
597 log_error("Forward-secure sealing not available.");
598 return -EOPNOTSUPP;
599 #endif
600
601 case 'p': {
602 const char *dots;
603
604 dots = strstr(optarg, "..");
605 if (dots) {
606 char *a;
607 int from, to, i;
608
609 /* a range */
610 a = strndup(optarg, dots - optarg);
611 if (!a)
612 return log_oom();
613
614 from = log_level_from_string(a);
615 to = log_level_from_string(dots + 2);
616 free(a);
617
618 if (from < 0 || to < 0) {
619 log_error("Failed to parse log level range %s", optarg);
620 return -EINVAL;
621 }
622
623 arg_priorities = 0;
624
625 if (from < to) {
626 for (i = from; i <= to; i++)
627 arg_priorities |= 1 << i;
628 } else {
629 for (i = to; i <= from; i++)
630 arg_priorities |= 1 << i;
631 }
632
633 } else {
634 int p, i;
635
636 p = log_level_from_string(optarg);
637 if (p < 0) {
638 log_error("Unknown log level %s", optarg);
639 return -EINVAL;
640 }
641
642 arg_priorities = 0;
643
644 for (i = 0; i <= p; i++)
645 arg_priorities |= 1 << i;
646 }
647
648 break;
649 }
650
651 case 'S':
652 r = parse_timestamp(optarg, &arg_since);
653 if (r < 0) {
654 log_error("Failed to parse timestamp: %s", optarg);
655 return -EINVAL;
656 }
657 arg_since_set = true;
658 break;
659
660 case 'U':
661 r = parse_timestamp(optarg, &arg_until);
662 if (r < 0) {
663 log_error("Failed to parse timestamp: %s", optarg);
664 return -EINVAL;
665 }
666 arg_until_set = true;
667 break;
668
669 case 't':
670 r = strv_extend(&arg_syslog_identifier, optarg);
671 if (r < 0)
672 return log_oom();
673 break;
674
675 case 'u':
676 r = strv_extend(&arg_system_units, optarg);
677 if (r < 0)
678 return log_oom();
679 break;
680
681 case ARG_USER_UNIT:
682 r = strv_extend(&arg_user_units, optarg);
683 if (r < 0)
684 return log_oom();
685 break;
686
687 case 'F':
688 arg_field = optarg;
689 break;
690
691 case 'x':
692 arg_catalog = true;
693 break;
694
695 case ARG_LIST_CATALOG:
696 arg_action = ACTION_LIST_CATALOG;
697 break;
698
699 case ARG_DUMP_CATALOG:
700 arg_action = ACTION_DUMP_CATALOG;
701 break;
702
703 case ARG_UPDATE_CATALOG:
704 arg_action = ACTION_UPDATE_CATALOG;
705 break;
706
707 case 'r':
708 arg_reverse = true;
709 break;
710
711 case ARG_UTC:
712 arg_utc = true;
713 break;
714
715 case ARG_FLUSH:
716 arg_action = ACTION_FLUSH;
717 break;
718
719 case ARG_ROTATE:
720 arg_action = ACTION_ROTATE;
721 break;
722
723 case '?':
724 return -EINVAL;
725
726 default:
727 assert_not_reached("Unhandled option");
728 }
729
730 if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT)
731 arg_lines = 10;
732
733 if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
734 log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
735 return -EINVAL;
736 }
737
738 if (arg_since_set && arg_until_set && arg_since > arg_until) {
739 log_error("--since= must be before --until=.");
740 return -EINVAL;
741 }
742
743 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
744 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
745 return -EINVAL;
746 }
747
748 if (arg_follow && arg_reverse) {
749 log_error("Please specify either --reverse= or --follow=, not both.");
750 return -EINVAL;
751 }
752
753 if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc) {
754 log_error("Extraneous arguments starting with '%s'", argv[optind]);
755 return -EINVAL;
756 }
757
758 if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && (arg_file || arg_directory || arg_merge)) {
759 log_error("Using --boot or --list-boots with --file, --directory or --merge is not supported.");
760 return -EINVAL;
761 }
762
763 return 1;
764 }
765
766 static int generate_new_id128(void) {
767 sd_id128_t id;
768 int r;
769 unsigned i;
770
771 r = sd_id128_randomize(&id);
772 if (r < 0)
773 return log_error_errno(r, "Failed to generate ID: %m");
774
775 printf("As string:\n"
776 SD_ID128_FORMAT_STR "\n\n"
777 "As UUID:\n"
778 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
779 "As macro:\n"
780 "#define MESSAGE_XYZ SD_ID128_MAKE(",
781 SD_ID128_FORMAT_VAL(id),
782 SD_ID128_FORMAT_VAL(id));
783 for (i = 0; i < 16; i++)
784 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
785 fputs(")\n\n", stdout);
786
787 printf("As Python constant:\n"
788 ">>> import uuid\n"
789 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
790 SD_ID128_FORMAT_VAL(id));
791
792 return 0;
793 }
794
795 static int add_matches(sd_journal *j, char **args) {
796 char **i;
797 bool have_term = false;
798
799 assert(j);
800
801 STRV_FOREACH(i, args) {
802 int r;
803
804 if (streq(*i, "+")) {
805 if (!have_term)
806 break;
807 r = sd_journal_add_disjunction(j);
808 have_term = false;
809
810 } else if (path_is_absolute(*i)) {
811 _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
812 const char *path;
813 _cleanup_free_ char *interpreter = NULL;
814 struct stat st;
815
816 p = canonicalize_file_name(*i);
817 path = p ? p : *i;
818
819 if (lstat(path, &st) < 0)
820 return log_error_errno(errno, "Couldn't stat file: %m");
821
822 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
823 if (executable_is_script(path, &interpreter) > 0) {
824 _cleanup_free_ char *comm;
825
826 comm = strndup(basename(path), 15);
827 if (!comm)
828 return log_oom();
829
830 t = strappend("_COMM=", comm);
831
832 /* Append _EXE only if the interpreter is not a link.
833 Otherwise, it might be outdated often. */
834 if (lstat(interpreter, &st) == 0 &&
835 !S_ISLNK(st.st_mode)) {
836 t2 = strappend("_EXE=", interpreter);
837 if (!t2)
838 return log_oom();
839 }
840 } else
841 t = strappend("_EXE=", path);
842 } else if (S_ISCHR(st.st_mode))
843 (void) asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
844 else if (S_ISBLK(st.st_mode))
845 (void) asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
846 else {
847 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
848 return -EINVAL;
849 }
850
851 if (!t)
852 return log_oom();
853
854 r = sd_journal_add_match(j, t, 0);
855 if (t2)
856 r = sd_journal_add_match(j, t2, 0);
857 have_term = true;
858
859 } else {
860 r = sd_journal_add_match(j, *i, 0);
861 have_term = true;
862 }
863
864 if (r < 0)
865 return log_error_errno(r, "Failed to add match '%s': %m", *i);
866 }
867
868 if (!strv_isempty(args) && !have_term) {
869 log_error("\"+\" can only be used between terms");
870 return -EINVAL;
871 }
872
873 return 0;
874 }
875
876 static void boot_id_free_all(BootId *l) {
877
878 while (l) {
879 BootId *i = l;
880 LIST_REMOVE(boot_list, l, i);
881 free(i);
882 }
883 }
884
885 static int discover_next_boot(
886 sd_journal *j,
887 BootId **boot,
888 bool advance_older,
889 bool read_realtime) {
890
891 int r;
892 char match[9+32+1] = "_BOOT_ID=";
893 _cleanup_free_ BootId *next_boot = NULL;
894
895 assert(j);
896 assert(boot);
897
898 /* We expect the journal to be on the last position of a boot
899 * (in relation to the direction we are going), so that the next
900 * invocation of sd_journal_next/previous will be from a different
901 * boot. We then collect any information we desire and then jump
902 * to the last location of the new boot by using a _BOOT_ID match
903 * coming from the other journal direction. */
904
905 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
906 * we can actually advance to a *different* boot. */
907 sd_journal_flush_matches(j);
908
909 if (advance_older)
910 r = sd_journal_previous(j);
911 else
912 r = sd_journal_next(j);
913 if (r < 0)
914 return r;
915 else if (r == 0)
916 return 0; /* End of journal, yay. */
917
918 next_boot = new0(BootId, 1);
919 if (!next_boot)
920 return -ENOMEM;
921
922 r = sd_journal_get_monotonic_usec(j, NULL, &next_boot->id);
923 if (r < 0)
924 return r;
925
926 if (read_realtime) {
927 r = sd_journal_get_realtime_usec(j, &next_boot->first);
928 if (r < 0)
929 return r;
930 }
931
932 /* Now seek to the last occurrence of this boot ID. */
933 sd_id128_to_string(next_boot->id, match + 9);
934 r = sd_journal_add_match(j, match, sizeof(match) - 1);
935 if (r < 0)
936 return r;
937
938 if (advance_older)
939 r = sd_journal_seek_head(j);
940 else
941 r = sd_journal_seek_tail(j);
942 if (r < 0)
943 return r;
944
945 if (advance_older)
946 r = sd_journal_next(j);
947 else
948 r = sd_journal_previous(j);
949 if (r < 0)
950 return r;
951 else if (r == 0)
952 return -ENODATA; /* This shouldn't happen. We just came from this very boot ID. */
953
954 if (read_realtime) {
955 r = sd_journal_get_realtime_usec(j, &next_boot->last);
956 if (r < 0)
957 return r;
958 }
959
960 *boot = next_boot;
961 next_boot = NULL;
962
963 return 0;
964 }
965
966 static int get_boots(
967 sd_journal *j,
968 BootId **boots,
969 BootId *query_ref_boot,
970 int ref_boot_offset) {
971
972 bool skip_once;
973 int r, count = 0;
974 BootId *head = NULL, *tail = NULL;
975 const bool advance_older = query_ref_boot && ref_boot_offset <= 0;
976
977 assert(j);
978
979 /* Adjust for the asymmetry that offset 0 is
980 * the last (and current) boot, while 1 is considered the
981 * (chronological) first boot in the journal. */
982 skip_once = query_ref_boot && sd_id128_is_null(query_ref_boot->id) && ref_boot_offset < 0;
983
984 /* Advance to the earliest/latest occurrence of our reference
985 * boot ID (taking our lookup direction into account), so that
986 * discover_next_boot() can do its job.
987 * If no reference is given, the journal head/tail will do,
988 * they're "virtual" boots after all. */
989 if (query_ref_boot && !sd_id128_is_null(query_ref_boot->id)) {
990 char match[9+32+1] = "_BOOT_ID=";
991
992 sd_journal_flush_matches(j);
993
994 sd_id128_to_string(query_ref_boot->id, match + 9);
995 r = sd_journal_add_match(j, match, sizeof(match) - 1);
996 if (r < 0)
997 return r;
998
999 if (advance_older)
1000 r = sd_journal_seek_head(j);
1001 else
1002 r = sd_journal_seek_tail(j);
1003 if (r < 0)
1004 return r;
1005
1006 if (advance_older)
1007 r = sd_journal_next(j);
1008 else
1009 r = sd_journal_previous(j);
1010 if (r < 0)
1011 return r;
1012 else if (r == 0)
1013 goto finish;
1014 else if (ref_boot_offset == 0) {
1015 count = 1;
1016 goto finish;
1017 }
1018 } else {
1019 if (advance_older)
1020 r = sd_journal_seek_tail(j);
1021 else
1022 r = sd_journal_seek_head(j);
1023 if (r < 0)
1024 return r;
1025
1026 /* No sd_journal_next/previous here. */
1027 }
1028
1029 for (;;) {
1030 _cleanup_free_ BootId *current = NULL;
1031
1032 r = discover_next_boot(j, &current, advance_older, !query_ref_boot);
1033 if (r < 0) {
1034 boot_id_free_all(head);
1035 return r;
1036 }
1037
1038 if (!current)
1039 break;
1040
1041 if (query_ref_boot) {
1042 if (!skip_once)
1043 ref_boot_offset += advance_older ? 1 : -1;
1044 skip_once = false;
1045
1046 if (ref_boot_offset == 0) {
1047 count = 1;
1048 query_ref_boot->id = current->id;
1049 break;
1050 }
1051 } else {
1052 LIST_INSERT_AFTER(boot_list, head, tail, current);
1053 tail = current;
1054 current = NULL;
1055 count++;
1056 }
1057 }
1058
1059 finish:
1060 if (boots)
1061 *boots = head;
1062
1063 sd_journal_flush_matches(j);
1064
1065 return count;
1066 }
1067
1068 static int list_boots(sd_journal *j) {
1069 int w, i, count;
1070 BootId *id, *all_ids;
1071
1072 assert(j);
1073
1074 count = get_boots(j, &all_ids, NULL, 0);
1075 if (count < 0)
1076 return log_error_errno(count, "Failed to determine boots: %m");
1077 if (count == 0)
1078 return count;
1079
1080 pager_open_if_enabled();
1081
1082 /* numbers are one less, but we need an extra char for the sign */
1083 w = DECIMAL_STR_WIDTH(count - 1) + 1;
1084
1085 i = 0;
1086 LIST_FOREACH(boot_list, id, all_ids) {
1087 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
1088
1089 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
1090 w, i - count + 1,
1091 SD_ID128_FORMAT_VAL(id->id),
1092 format_timestamp_maybe_utc(a, sizeof(a), id->first),
1093 format_timestamp_maybe_utc(b, sizeof(b), id->last));
1094 i++;
1095 }
1096
1097 boot_id_free_all(all_ids);
1098
1099 return 0;
1100 }
1101
1102 static int add_boot(sd_journal *j) {
1103 char match[9+32+1] = "_BOOT_ID=";
1104 int r;
1105 BootId ref_boot_id = {};
1106
1107 assert(j);
1108
1109 if (!arg_boot)
1110 return 0;
1111
1112 if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
1113 return add_match_this_boot(j, arg_machine);
1114
1115 ref_boot_id.id = arg_boot_id;
1116 r = get_boots(j, NULL, &ref_boot_id, arg_boot_offset);
1117 assert(r <= 1);
1118 if (r <= 0) {
1119 const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
1120
1121 if (sd_id128_is_null(arg_boot_id))
1122 log_error("Failed to look up boot %+i: %s", arg_boot_offset, reason);
1123 else
1124 log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
1125 SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, reason);
1126
1127 return r == 0 ? -ENODATA : r;
1128 }
1129
1130 sd_id128_to_string(ref_boot_id.id, match + 9);
1131
1132 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1133 if (r < 0)
1134 return log_error_errno(r, "Failed to add match: %m");
1135
1136 r = sd_journal_add_conjunction(j);
1137 if (r < 0)
1138 return log_error_errno(r, "Failed to add conjunction: %m");
1139
1140 return 0;
1141 }
1142
1143 static int add_dmesg(sd_journal *j) {
1144 int r;
1145 assert(j);
1146
1147 if (!arg_dmesg)
1148 return 0;
1149
1150 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1151 if (r < 0)
1152 return log_error_errno(r, "Failed to add match: %m");
1153
1154 r = sd_journal_add_conjunction(j);
1155 if (r < 0)
1156 return log_error_errno(r, "Failed to add conjunction: %m");
1157
1158 return 0;
1159 }
1160
1161 static int get_possible_units(
1162 sd_journal *j,
1163 const char *fields,
1164 char **patterns,
1165 Set **units) {
1166
1167 _cleanup_set_free_free_ Set *found;
1168 const char *field;
1169 int r;
1170
1171 found = set_new(&string_hash_ops);
1172 if (!found)
1173 return -ENOMEM;
1174
1175 NULSTR_FOREACH(field, fields) {
1176 const void *data;
1177 size_t size;
1178
1179 r = sd_journal_query_unique(j, field);
1180 if (r < 0)
1181 return r;
1182
1183 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1184 char **pattern, *eq;
1185 size_t prefix;
1186 _cleanup_free_ char *u = NULL;
1187
1188 eq = memchr(data, '=', size);
1189 if (eq)
1190 prefix = eq - (char*) data + 1;
1191 else
1192 prefix = 0;
1193
1194 u = strndup((char*) data + prefix, size - prefix);
1195 if (!u)
1196 return -ENOMEM;
1197
1198 STRV_FOREACH(pattern, patterns)
1199 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1200 log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1201
1202 r = set_consume(found, u);
1203 u = NULL;
1204 if (r < 0 && r != -EEXIST)
1205 return r;
1206
1207 break;
1208 }
1209 }
1210 }
1211
1212 *units = found;
1213 found = NULL;
1214 return 0;
1215 }
1216
1217 /* This list is supposed to return the superset of unit names
1218 * possibly matched by rules added with add_matches_for_unit... */
1219 #define SYSTEM_UNITS \
1220 "_SYSTEMD_UNIT\0" \
1221 "COREDUMP_UNIT\0" \
1222 "UNIT\0" \
1223 "OBJECT_SYSTEMD_UNIT\0" \
1224 "_SYSTEMD_SLICE\0"
1225
1226 /* ... and add_matches_for_user_unit */
1227 #define USER_UNITS \
1228 "_SYSTEMD_USER_UNIT\0" \
1229 "USER_UNIT\0" \
1230 "COREDUMP_USER_UNIT\0" \
1231 "OBJECT_SYSTEMD_USER_UNIT\0"
1232
1233 static int add_units(sd_journal *j) {
1234 _cleanup_strv_free_ char **patterns = NULL;
1235 int r, count = 0;
1236 char **i;
1237
1238 assert(j);
1239
1240 STRV_FOREACH(i, arg_system_units) {
1241 _cleanup_free_ char *u = NULL;
1242
1243 r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
1244 if (r < 0)
1245 return r;
1246
1247 if (string_is_glob(u)) {
1248 r = strv_push(&patterns, u);
1249 if (r < 0)
1250 return r;
1251 u = NULL;
1252 } else {
1253 r = add_matches_for_unit(j, u);
1254 if (r < 0)
1255 return r;
1256 r = sd_journal_add_disjunction(j);
1257 if (r < 0)
1258 return r;
1259 count ++;
1260 }
1261 }
1262
1263 if (!strv_isempty(patterns)) {
1264 _cleanup_set_free_free_ Set *units = NULL;
1265 Iterator it;
1266 char *u;
1267
1268 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1269 if (r < 0)
1270 return r;
1271
1272 SET_FOREACH(u, units, it) {
1273 r = add_matches_for_unit(j, u);
1274 if (r < 0)
1275 return r;
1276 r = sd_journal_add_disjunction(j);
1277 if (r < 0)
1278 return r;
1279 count ++;
1280 }
1281 }
1282
1283 patterns = strv_free(patterns);
1284
1285 STRV_FOREACH(i, arg_user_units) {
1286 _cleanup_free_ char *u = NULL;
1287
1288 r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
1289 if (r < 0)
1290 return r;
1291
1292 if (string_is_glob(u)) {
1293 r = strv_push(&patterns, u);
1294 if (r < 0)
1295 return r;
1296 u = NULL;
1297 } else {
1298 r = add_matches_for_user_unit(j, u, getuid());
1299 if (r < 0)
1300 return r;
1301 r = sd_journal_add_disjunction(j);
1302 if (r < 0)
1303 return r;
1304 count ++;
1305 }
1306 }
1307
1308 if (!strv_isempty(patterns)) {
1309 _cleanup_set_free_free_ Set *units = NULL;
1310 Iterator it;
1311 char *u;
1312
1313 r = get_possible_units(j, USER_UNITS, patterns, &units);
1314 if (r < 0)
1315 return r;
1316
1317 SET_FOREACH(u, units, it) {
1318 r = add_matches_for_user_unit(j, u, getuid());
1319 if (r < 0)
1320 return r;
1321 r = sd_journal_add_disjunction(j);
1322 if (r < 0)
1323 return r;
1324 count ++;
1325 }
1326 }
1327
1328 /* Complain if the user request matches but nothing whatsoever was
1329 * found, since otherwise everything would be matched. */
1330 if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1331 return -ENODATA;
1332
1333 r = sd_journal_add_conjunction(j);
1334 if (r < 0)
1335 return r;
1336
1337 return 0;
1338 }
1339
1340 static int add_priorities(sd_journal *j) {
1341 char match[] = "PRIORITY=0";
1342 int i, r;
1343 assert(j);
1344
1345 if (arg_priorities == 0xFF)
1346 return 0;
1347
1348 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1349 if (arg_priorities & (1 << i)) {
1350 match[sizeof(match)-2] = '0' + i;
1351
1352 r = sd_journal_add_match(j, match, strlen(match));
1353 if (r < 0)
1354 return log_error_errno(r, "Failed to add match: %m");
1355 }
1356
1357 r = sd_journal_add_conjunction(j);
1358 if (r < 0)
1359 return log_error_errno(r, "Failed to add conjunction: %m");
1360
1361 return 0;
1362 }
1363
1364
1365 static int add_syslog_identifier(sd_journal *j) {
1366 int r;
1367 char **i;
1368
1369 assert(j);
1370
1371 STRV_FOREACH(i, arg_syslog_identifier) {
1372 char *u;
1373
1374 u = strjoina("SYSLOG_IDENTIFIER=", *i);
1375 r = sd_journal_add_match(j, u, 0);
1376 if (r < 0)
1377 return r;
1378 r = sd_journal_add_disjunction(j);
1379 if (r < 0)
1380 return r;
1381 }
1382
1383 r = sd_journal_add_conjunction(j);
1384 if (r < 0)
1385 return r;
1386
1387 return 0;
1388 }
1389
1390 static int setup_keys(void) {
1391 #ifdef HAVE_GCRYPT
1392 size_t mpk_size, seed_size, state_size, i;
1393 uint8_t *mpk, *seed, *state;
1394 int fd = -1, r;
1395 sd_id128_t machine, boot;
1396 char *p = NULL, *k = NULL;
1397 struct FSSHeader h;
1398 uint64_t n;
1399 struct stat st;
1400
1401 r = stat("/var/log/journal", &st);
1402 if (r < 0 && errno != ENOENT && errno != ENOTDIR)
1403 return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal");
1404
1405 if (r < 0 || !S_ISDIR(st.st_mode)) {
1406 log_error("%s is not a directory, must be using persistent logging for FSS.",
1407 "/var/log/journal");
1408 return r < 0 ? -errno : -ENOTDIR;
1409 }
1410
1411 r = sd_id128_get_machine(&machine);
1412 if (r < 0)
1413 return log_error_errno(r, "Failed to get machine ID: %m");
1414
1415 r = sd_id128_get_boot(&boot);
1416 if (r < 0)
1417 return log_error_errno(r, "Failed to get boot ID: %m");
1418
1419 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1420 SD_ID128_FORMAT_VAL(machine)) < 0)
1421 return log_oom();
1422
1423 if (arg_force) {
1424 r = unlink(p);
1425 if (r < 0 && errno != ENOENT) {
1426 r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
1427 goto finish;
1428 }
1429 } else if (access(p, F_OK) >= 0) {
1430 log_error("Sealing key file %s exists already. Use --force to recreate.", p);
1431 r = -EEXIST;
1432 goto finish;
1433 }
1434
1435 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1436 SD_ID128_FORMAT_VAL(machine)) < 0) {
1437 r = log_oom();
1438 goto finish;
1439 }
1440
1441 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1442 mpk = alloca(mpk_size);
1443
1444 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1445 seed = alloca(seed_size);
1446
1447 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1448 state = alloca(state_size);
1449
1450 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1451 if (fd < 0) {
1452 r = log_error_errno(errno, "Failed to open /dev/random: %m");
1453 goto finish;
1454 }
1455
1456 log_info("Generating seed...");
1457 r = loop_read_exact(fd, seed, seed_size, true);
1458 if (r < 0) {
1459 log_error_errno(r, "Failed to read random seed: %m");
1460 goto finish;
1461 }
1462
1463 log_info("Generating key pair...");
1464 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1465
1466 log_info("Generating sealing key...");
1467 FSPRG_GenState0(state, mpk, seed, seed_size);
1468
1469 assert(arg_interval > 0);
1470
1471 n = now(CLOCK_REALTIME);
1472 n /= arg_interval;
1473
1474 safe_close(fd);
1475 fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1476 if (fd < 0) {
1477 r = log_error_errno(errno, "Failed to open %s: %m", k);
1478 goto finish;
1479 }
1480
1481 /* Enable secure remove, exclusion from dump, synchronous
1482 * writing and in-place updating */
1483 r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL);
1484 if (r < 0)
1485 log_warning_errno(errno, "Failed to set file attributes: %m");
1486
1487 zero(h);
1488 memcpy(h.signature, "KSHHRHLP", 8);
1489 h.machine_id = machine;
1490 h.boot_id = boot;
1491 h.header_size = htole64(sizeof(h));
1492 h.start_usec = htole64(n * arg_interval);
1493 h.interval_usec = htole64(arg_interval);
1494 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1495 h.fsprg_state_size = htole64(state_size);
1496
1497 r = loop_write(fd, &h, sizeof(h), false);
1498 if (r < 0) {
1499 log_error_errno(r, "Failed to write header: %m");
1500 goto finish;
1501 }
1502
1503 r = loop_write(fd, state, state_size, false);
1504 if (r < 0) {
1505 log_error_errno(r, "Failed to write state: %m");
1506 goto finish;
1507 }
1508
1509 if (link(k, p) < 0) {
1510 r = log_error_errno(errno, "Failed to link file: %m");
1511 goto finish;
1512 }
1513
1514 if (on_tty()) {
1515 fprintf(stderr,
1516 "\n"
1517 "The new key pair has been generated. The " ANSI_HIGHLIGHT "secret sealing key" ANSI_NORMAL " has been written to\n"
1518 "the following local file. This key file is automatically updated when the\n"
1519 "sealing key is advanced. It should not be used on multiple hosts.\n"
1520 "\n"
1521 "\t%s\n"
1522 "\n"
1523 "Please write down the following " ANSI_HIGHLIGHT "secret verification key" ANSI_NORMAL ". It should be stored\n"
1524 "at a safe location and should not be saved locally on disk.\n"
1525 "\n\t" ANSI_HIGHLIGHT_RED, p);
1526 fflush(stderr);
1527 }
1528 for (i = 0; i < seed_size; i++) {
1529 if (i > 0 && i % 3 == 0)
1530 putchar('-');
1531 printf("%02x", ((uint8_t*) seed)[i]);
1532 }
1533
1534 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1535
1536 if (on_tty()) {
1537 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1538
1539 fprintf(stderr,
1540 ANSI_NORMAL "\n"
1541 "The sealing key is automatically changed every %s.\n",
1542 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1543
1544 hn = gethostname_malloc();
1545
1546 if (hn) {
1547 hostname_cleanup(hn);
1548 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1549 } else
1550 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1551
1552 #ifdef HAVE_QRENCODE
1553 /* If this is not an UTF-8 system don't print any QR codes */
1554 if (is_locale_utf8()) {
1555 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1556 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1557 }
1558 #endif
1559 free(hn);
1560 }
1561
1562 r = 0;
1563
1564 finish:
1565 safe_close(fd);
1566
1567 if (k) {
1568 unlink(k);
1569 free(k);
1570 }
1571
1572 free(p);
1573
1574 return r;
1575 #else
1576 log_error("Forward-secure sealing not available.");
1577 return -EOPNOTSUPP;
1578 #endif
1579 }
1580
1581 static int verify(sd_journal *j) {
1582 int r = 0;
1583 Iterator i;
1584 JournalFile *f;
1585
1586 assert(j);
1587
1588 log_show_color(true);
1589
1590 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1591 int k;
1592 usec_t first = 0, validated = 0, last = 0;
1593
1594 #ifdef HAVE_GCRYPT
1595 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1596 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1597 #endif
1598
1599 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1600 if (k == -EINVAL) {
1601 /* If the key was invalid give up right-away. */
1602 return k;
1603 } else if (k < 0) {
1604 log_warning_errno(k, "FAIL: %s (%m)", f->path);
1605 r = k;
1606 } else {
1607 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1608 log_info("PASS: %s", f->path);
1609
1610 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1611 if (validated > 0) {
1612 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1613 format_timestamp_maybe_utc(a, sizeof(a), first),
1614 format_timestamp_maybe_utc(b, sizeof(b), validated),
1615 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1616 } else if (last > 0)
1617 log_info("=> No sealing yet, %s of entries not sealed.",
1618 format_timespan(c, sizeof(c), last - first, 0));
1619 else
1620 log_info("=> No sealing yet, no entries in file.");
1621 }
1622 }
1623 }
1624
1625 return r;
1626 }
1627
1628 static int access_check_var_log_journal(sd_journal *j) {
1629 #ifdef HAVE_ACL
1630 _cleanup_strv_free_ char **g = NULL;
1631 const char* dir;
1632 #endif
1633 int r;
1634
1635 assert(j);
1636
1637 if (arg_quiet)
1638 return 0;
1639
1640 /* If we are root, we should have access, don't warn. */
1641 if (getuid() == 0)
1642 return 0;
1643
1644 /* If we are in the 'systemd-journal' group, we should have
1645 * access too. */
1646 r = in_group("systemd-journal");
1647 if (r < 0)
1648 return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m");
1649 if (r > 0)
1650 return 0;
1651
1652 #ifdef HAVE_ACL
1653 if (laccess("/run/log/journal", F_OK) >= 0)
1654 dir = "/run/log/journal";
1655 else
1656 dir = "/var/log/journal";
1657
1658 /* If we are in any of the groups listed in the journal ACLs,
1659 * then all is good, too. Let's enumerate all groups from the
1660 * default ACL of the directory, which generally should allow
1661 * access to most journal files too. */
1662 r = acl_search_groups(dir, &g);
1663 if (r < 0)
1664 return log_error_errno(r, "Failed to search journal ACL: %m");
1665 if (r > 0)
1666 return 0;
1667
1668 /* Print a pretty list, if there were ACLs set. */
1669 if (!strv_isempty(g)) {
1670 _cleanup_free_ char *s = NULL;
1671
1672 /* Thre are groups in the ACL, let's list them */
1673 r = strv_extend(&g, "systemd-journal");
1674 if (r < 0)
1675 return log_oom();
1676
1677 strv_sort(g);
1678 strv_uniq(g);
1679
1680 s = strv_join(g, "', '");
1681 if (!s)
1682 return log_oom();
1683
1684 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1685 " Users in groups '%s' can see all messages.\n"
1686 " Pass -q to turn off this notice.", s);
1687 return 1;
1688 }
1689 #endif
1690
1691 /* If no ACLs were found, print a short version of the message. */
1692 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1693 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1694 " turn off this notice.");
1695
1696 return 1;
1697 }
1698
1699 static int access_check(sd_journal *j) {
1700 Iterator it;
1701 void *code;
1702 int r = 0;
1703
1704 assert(j);
1705
1706 if (set_isempty(j->errors)) {
1707 if (ordered_hashmap_isempty(j->files))
1708 log_notice("No journal files were found.");
1709
1710 return 0;
1711 }
1712
1713 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1714 (void) access_check_var_log_journal(j);
1715
1716 if (ordered_hashmap_isempty(j->files))
1717 r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
1718 }
1719
1720 SET_FOREACH(code, j->errors, it) {
1721 int err;
1722
1723 err = -PTR_TO_INT(code);
1724 assert(err > 0);
1725
1726 if (err == EACCES)
1727 continue;
1728
1729 log_warning_errno(err, "Error was encountered while opening journal files: %m");
1730 if (r == 0)
1731 r = -err;
1732 }
1733
1734 return r;
1735 }
1736
1737 static int flush_to_var(void) {
1738 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1739 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
1740 _cleanup_close_ int watch_fd = -1;
1741 int r;
1742
1743 /* Quick exit */
1744 if (access("/run/systemd/journal/flushed", F_OK) >= 0)
1745 return 0;
1746
1747 /* OK, let's actually do the full logic, send SIGUSR1 to the
1748 * daemon and set up inotify to wait for the flushed file to appear */
1749 r = bus_connect_system_systemd(&bus);
1750 if (r < 0)
1751 return log_error_errno(r, "Failed to get D-Bus connection: %m");
1752
1753 r = sd_bus_call_method(
1754 bus,
1755 "org.freedesktop.systemd1",
1756 "/org/freedesktop/systemd1",
1757 "org.freedesktop.systemd1.Manager",
1758 "KillUnit",
1759 &error,
1760 NULL,
1761 "ssi", "systemd-journald.service", "main", SIGUSR1);
1762 if (r < 0) {
1763 log_error("Failed to kill journal service: %s", bus_error_message(&error, r));
1764 return r;
1765 }
1766
1767 mkdir_p("/run/systemd/journal", 0755);
1768
1769 watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1770 if (watch_fd < 0)
1771 return log_error_errno(errno, "Failed to create inotify watch: %m");
1772
1773 r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_CREATE|IN_DONT_FOLLOW|IN_ONLYDIR);
1774 if (r < 0)
1775 return log_error_errno(errno, "Failed to watch journal directory: %m");
1776
1777 for (;;) {
1778 if (access("/run/systemd/journal/flushed", F_OK) >= 0)
1779 break;
1780
1781 if (errno != ENOENT)
1782 return log_error_errno(errno, "Failed to check for existence of /run/systemd/journal/flushed: %m");
1783
1784 r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
1785 if (r < 0)
1786 return log_error_errno(r, "Failed to wait for event: %m");
1787
1788 r = flush_fd(watch_fd);
1789 if (r < 0)
1790 return log_error_errno(r, "Failed to flush inotify events: %m");
1791 }
1792
1793 return 0;
1794 }
1795
1796 static int rotate(void) {
1797 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1798 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
1799 int r;
1800
1801 r = bus_connect_system_systemd(&bus);
1802 if (r < 0)
1803 return log_error_errno(r, "Failed to get D-Bus connection: %m");
1804
1805 r = sd_bus_call_method(
1806 bus,
1807 "org.freedesktop.systemd1",
1808 "/org/freedesktop/systemd1",
1809 "org.freedesktop.systemd1.Manager",
1810 "KillUnit",
1811 &error,
1812 NULL,
1813 "ssi", "systemd-journald.service", "main", SIGUSR2);
1814 if (r < 0)
1815 return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
1816
1817 return 0;
1818 }
1819
1820 int main(int argc, char *argv[]) {
1821 int r;
1822 _cleanup_journal_close_ sd_journal *j = NULL;
1823 bool need_seek = false;
1824 sd_id128_t previous_boot_id;
1825 bool previous_boot_id_valid = false, first_line = true;
1826 int n_shown = 0;
1827 bool ellipsized = false;
1828
1829 setlocale(LC_ALL, "");
1830 log_parse_environment();
1831 log_open();
1832
1833 r = parse_argv(argc, argv);
1834 if (r <= 0)
1835 goto finish;
1836
1837 signal(SIGWINCH, columns_lines_cache_reset);
1838 sigbus_install();
1839
1840 /* Increase max number of open files to 16K if we can, we
1841 * might needs this when browsing journal files, which might
1842 * be split up into many files. */
1843 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
1844
1845 if (arg_action == ACTION_NEW_ID128) {
1846 r = generate_new_id128();
1847 goto finish;
1848 }
1849
1850 if (arg_action == ACTION_FLUSH) {
1851 r = flush_to_var();
1852 goto finish;
1853 }
1854
1855 if (arg_action == ACTION_ROTATE) {
1856 r = rotate();
1857 goto finish;
1858 }
1859
1860 if (arg_action == ACTION_SETUP_KEYS) {
1861 r = setup_keys();
1862 goto finish;
1863 }
1864
1865 if (arg_action == ACTION_UPDATE_CATALOG ||
1866 arg_action == ACTION_LIST_CATALOG ||
1867 arg_action == ACTION_DUMP_CATALOG) {
1868
1869 _cleanup_free_ char *database;
1870
1871 database = path_join(arg_root, CATALOG_DATABASE, NULL);
1872 if (!database) {
1873 r = log_oom();
1874 goto finish;
1875 }
1876
1877 if (arg_action == ACTION_UPDATE_CATALOG) {
1878 r = catalog_update(database, arg_root, catalog_file_dirs);
1879 if (r < 0)
1880 log_error_errno(r, "Failed to list catalog: %m");
1881 } else {
1882 bool oneline = arg_action == ACTION_LIST_CATALOG;
1883
1884 pager_open_if_enabled();
1885 if (optind < argc)
1886 r = catalog_list_items(stdout, database,
1887 oneline, argv + optind);
1888 else
1889 r = catalog_list(stdout, database, oneline);
1890 if (r < 0)
1891 log_error_errno(r, "Failed to list catalog: %m");
1892 }
1893
1894 goto finish;
1895 }
1896
1897 if (arg_directory)
1898 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1899 else if (arg_file)
1900 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1901 else if (arg_machine)
1902 r = sd_journal_open_container(&j, arg_machine, 0);
1903 else
1904 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1905 if (r < 0) {
1906 log_error_errno(r, "Failed to open %s: %m",
1907 arg_directory ? arg_directory : arg_file ? "files" : "journal");
1908 goto finish;
1909 }
1910
1911 r = access_check(j);
1912 if (r < 0)
1913 goto finish;
1914
1915 if (arg_action == ACTION_VERIFY) {
1916 r = verify(j);
1917 goto finish;
1918 }
1919
1920 if (arg_action == ACTION_PRINT_HEADER) {
1921 journal_print_header(j);
1922 r = 0;
1923 goto finish;
1924 }
1925
1926 if (arg_action == ACTION_DISK_USAGE) {
1927 uint64_t bytes = 0;
1928 char sbytes[FORMAT_BYTES_MAX];
1929
1930 r = sd_journal_get_usage(j, &bytes);
1931 if (r < 0)
1932 goto finish;
1933
1934 printf("Archived and active journals take up %s on disk.\n",
1935 format_bytes(sbytes, sizeof(sbytes), bytes));
1936 goto finish;
1937 }
1938
1939 if (arg_action == ACTION_VACUUM) {
1940 Directory *d;
1941 Iterator i;
1942
1943 HASHMAP_FOREACH(d, j->directories_by_path, i) {
1944 int q;
1945
1946 if (d->is_root)
1947 continue;
1948
1949 q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, true);
1950 if (q < 0) {
1951 log_error_errno(q, "Failed to vacuum %s: %m", d->path);
1952 r = q;
1953 }
1954 }
1955
1956 goto finish;
1957 }
1958
1959 if (arg_action == ACTION_LIST_BOOTS) {
1960 r = list_boots(j);
1961 goto finish;
1962 }
1963
1964 /* add_boot() must be called first!
1965 * It may need to seek the journal to find parent boot IDs. */
1966 r = add_boot(j);
1967 if (r < 0)
1968 goto finish;
1969
1970 r = add_dmesg(j);
1971 if (r < 0)
1972 goto finish;
1973
1974 r = add_units(j);
1975 if (r < 0) {
1976 log_error_errno(r, "Failed to add filter for units: %m");
1977 goto finish;
1978 }
1979
1980 r = add_syslog_identifier(j);
1981 if (r < 0) {
1982 log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
1983 goto finish;
1984 }
1985
1986 r = add_priorities(j);
1987 if (r < 0)
1988 goto finish;
1989
1990 r = add_matches(j, argv + optind);
1991 if (r < 0)
1992 goto finish;
1993
1994 if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
1995 _cleanup_free_ char *filter;
1996
1997 filter = journal_make_match_string(j);
1998 if (!filter)
1999 return log_oom();
2000
2001 log_debug("Journal filter: %s", filter);
2002 }
2003
2004 if (arg_field) {
2005 const void *data;
2006 size_t size;
2007
2008 r = sd_journal_set_data_threshold(j, 0);
2009 if (r < 0) {
2010 log_error_errno(r, "Failed to unset data size threshold: %m");
2011 goto finish;
2012 }
2013
2014 r = sd_journal_query_unique(j, arg_field);
2015 if (r < 0) {
2016 log_error_errno(r, "Failed to query unique data objects: %m");
2017 goto finish;
2018 }
2019
2020 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
2021 const void *eq;
2022
2023 if (arg_lines >= 0 && n_shown >= arg_lines)
2024 break;
2025
2026 eq = memchr(data, '=', size);
2027 if (eq)
2028 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
2029 else
2030 printf("%.*s\n", (int) size, (const char*) data);
2031
2032 n_shown ++;
2033 }
2034
2035 r = 0;
2036 goto finish;
2037 }
2038
2039 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2040 if (arg_follow) {
2041 r = sd_journal_get_fd(j);
2042 if (r < 0) {
2043 log_error_errno(r, "Failed to get journal fd: %m");
2044 goto finish;
2045 }
2046 }
2047
2048 if (arg_cursor || arg_after_cursor) {
2049 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
2050 if (r < 0) {
2051 log_error_errno(r, "Failed to seek to cursor: %m");
2052 goto finish;
2053 }
2054
2055 if (!arg_reverse)
2056 r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
2057 else
2058 r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
2059
2060 if (arg_after_cursor && r < 2) {
2061 /* We couldn't find the next entry after the cursor. */
2062 if (arg_follow)
2063 need_seek = true;
2064 else
2065 arg_lines = 0;
2066 }
2067
2068 } else if (arg_since_set && !arg_reverse) {
2069 r = sd_journal_seek_realtime_usec(j, arg_since);
2070 if (r < 0) {
2071 log_error_errno(r, "Failed to seek to date: %m");
2072 goto finish;
2073 }
2074 r = sd_journal_next(j);
2075
2076 } else if (arg_until_set && arg_reverse) {
2077 r = sd_journal_seek_realtime_usec(j, arg_until);
2078 if (r < 0) {
2079 log_error_errno(r, "Failed to seek to date: %m");
2080 goto finish;
2081 }
2082 r = sd_journal_previous(j);
2083
2084 } else if (arg_lines >= 0) {
2085 r = sd_journal_seek_tail(j);
2086 if (r < 0) {
2087 log_error_errno(r, "Failed to seek to tail: %m");
2088 goto finish;
2089 }
2090
2091 r = sd_journal_previous_skip(j, arg_lines);
2092
2093 } else if (arg_reverse) {
2094 r = sd_journal_seek_tail(j);
2095 if (r < 0) {
2096 log_error_errno(r, "Failed to seek to tail: %m");
2097 goto finish;
2098 }
2099
2100 r = sd_journal_previous(j);
2101
2102 } else {
2103 r = sd_journal_seek_head(j);
2104 if (r < 0) {
2105 log_error_errno(r, "Failed to seek to head: %m");
2106 goto finish;
2107 }
2108
2109 r = sd_journal_next(j);
2110 }
2111
2112 if (r < 0) {
2113 log_error_errno(r, "Failed to iterate through journal: %m");
2114 goto finish;
2115 }
2116 if (r == 0) {
2117 if (arg_follow)
2118 need_seek = true;
2119 else {
2120 printf("-- No entries --\n");
2121 goto finish;
2122 }
2123 }
2124
2125 if (!arg_follow)
2126 pager_open_if_enabled();
2127
2128 if (!arg_quiet) {
2129 usec_t start, end;
2130 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
2131
2132 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
2133 if (r < 0) {
2134 log_error_errno(r, "Failed to get cutoff: %m");
2135 goto finish;
2136 }
2137
2138 if (r > 0) {
2139 if (arg_follow)
2140 printf("-- Logs begin at %s. --\n",
2141 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start));
2142 else
2143 printf("-- Logs begin at %s, end at %s. --\n",
2144 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start),
2145 format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end));
2146 }
2147 }
2148
2149 for (;;) {
2150 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
2151 int flags;
2152
2153 if (need_seek) {
2154 if (!arg_reverse)
2155 r = sd_journal_next(j);
2156 else
2157 r = sd_journal_previous(j);
2158 if (r < 0) {
2159 log_error_errno(r, "Failed to iterate through journal: %m");
2160 goto finish;
2161 }
2162 if (r == 0)
2163 break;
2164 }
2165
2166 if (arg_until_set && !arg_reverse) {
2167 usec_t usec;
2168
2169 r = sd_journal_get_realtime_usec(j, &usec);
2170 if (r < 0) {
2171 log_error_errno(r, "Failed to determine timestamp: %m");
2172 goto finish;
2173 }
2174 if (usec > arg_until)
2175 goto finish;
2176 }
2177
2178 if (arg_since_set && arg_reverse) {
2179 usec_t usec;
2180
2181 r = sd_journal_get_realtime_usec(j, &usec);
2182 if (r < 0) {
2183 log_error_errno(r, "Failed to determine timestamp: %m");
2184 goto finish;
2185 }
2186 if (usec < arg_since)
2187 goto finish;
2188 }
2189
2190 if (!arg_merge && !arg_quiet) {
2191 sd_id128_t boot_id;
2192
2193 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
2194 if (r >= 0) {
2195 if (previous_boot_id_valid &&
2196 !sd_id128_equal(boot_id, previous_boot_id))
2197 printf("%s-- Reboot --%s\n",
2198 ansi_highlight(), ansi_normal());
2199
2200 previous_boot_id = boot_id;
2201 previous_boot_id_valid = true;
2202 }
2203 }
2204
2205 flags =
2206 arg_all * OUTPUT_SHOW_ALL |
2207 arg_full * OUTPUT_FULL_WIDTH |
2208 on_tty() * OUTPUT_COLOR |
2209 arg_catalog * OUTPUT_CATALOG |
2210 arg_utc * OUTPUT_UTC;
2211
2212 r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
2213 need_seek = true;
2214 if (r == -EADDRNOTAVAIL)
2215 break;
2216 else if (r < 0 || ferror(stdout))
2217 goto finish;
2218
2219 n_shown++;
2220 }
2221
2222 if (!arg_follow) {
2223 if (arg_show_cursor) {
2224 _cleanup_free_ char *cursor = NULL;
2225
2226 r = sd_journal_get_cursor(j, &cursor);
2227 if (r < 0 && r != -EADDRNOTAVAIL)
2228 log_error_errno(r, "Failed to get cursor: %m");
2229 else if (r >= 0)
2230 printf("-- cursor: %s\n", cursor);
2231 }
2232
2233 break;
2234 }
2235
2236 r = sd_journal_wait(j, (uint64_t) -1);
2237 if (r < 0) {
2238 log_error_errno(r, "Couldn't wait for journal event: %m");
2239 goto finish;
2240 }
2241
2242 first_line = false;
2243 }
2244
2245 finish:
2246 pager_close();
2247
2248 strv_free(arg_file);
2249
2250 strv_free(arg_syslog_identifier);
2251 strv_free(arg_system_units);
2252 strv_free(arg_user_units);
2253
2254 free(arg_root);
2255
2256 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2257 }