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