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