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