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