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