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