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