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