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