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