chiark / gitweb /
Add utility function to append root to path
[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 the system journal\n"
171                "     --user                Show 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         if (arg_action != ACTION_SHOW && optind < argc) {
662                 log_error("Extraneous arguments starting with '%s'", argv[optind]);
663                 return -EINVAL;
664         }
665
666         return 1;
667 }
668
669 static int generate_new_id128(void) {
670         sd_id128_t id;
671         int r;
672         unsigned i;
673
674         r = sd_id128_randomize(&id);
675         if (r < 0) {
676                 log_error("Failed to generate ID: %s", strerror(-r));
677                 return r;
678         }
679
680         printf("As string:\n"
681                SD_ID128_FORMAT_STR "\n\n"
682                "As UUID:\n"
683                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
684                "As macro:\n"
685                "#define MESSAGE_XYZ SD_ID128_MAKE(",
686                SD_ID128_FORMAT_VAL(id),
687                SD_ID128_FORMAT_VAL(id));
688         for (i = 0; i < 16; i++)
689                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
690         fputs(")\n\n", stdout);
691
692         printf("As Python constant:\n"
693                ">>> import uuid\n"
694                ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
695                SD_ID128_FORMAT_VAL(id));
696
697         return 0;
698 }
699
700 static int add_matches(sd_journal *j, char **args) {
701         char **i;
702         bool have_term = false;
703
704         assert(j);
705
706         STRV_FOREACH(i, args) {
707                 int r;
708
709                 if (streq(*i, "+")) {
710                         if (!have_term)
711                                 break;
712                         r = sd_journal_add_disjunction(j);
713                         have_term = false;
714
715                 } else if (path_is_absolute(*i)) {
716                         _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
717                         const char *path;
718                         _cleanup_free_ char *interpreter = NULL;
719                         struct stat st;
720
721                         p = canonicalize_file_name(*i);
722                         path = p ? p : *i;
723
724                         if (stat(path, &st) < 0)  {
725                                 log_error("Couldn't stat file: %m");
726                                 return -errno;
727                         }
728
729                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
730                                 if (executable_is_script(path, &interpreter) > 0) {
731                                         _cleanup_free_ char *comm;
732
733                                         comm = strndup(basename(path), 15);
734                                         if (!comm)
735                                                 return log_oom();
736
737                                         t = strappend("_COMM=", comm);
738
739                                         /* Append _EXE only if the interpreter is not a link.
740                                            Otherwise, it might be outdated often. */
741                                         if (lstat(interpreter, &st) == 0 &&
742                                             !S_ISLNK(st.st_mode)) {
743                                                 t2 = strappend("_EXE=", interpreter);
744                                                 if (!t2)
745                                                         return log_oom();
746                                         }
747                                 } else
748                                         t = strappend("_EXE=", path);
749                         } else if (S_ISCHR(st.st_mode)) {
750                                 if (asprintf(&t, "_KERNEL_DEVICE=c%u:%u",
751                                              major(st.st_rdev),
752                                              minor(st.st_rdev)) < 0)
753                                         return -ENOMEM;
754                         } else if (S_ISBLK(st.st_mode)) {
755                                 if (asprintf(&t, "_KERNEL_DEVICE=b%u:%u",
756                                              major(st.st_rdev),
757                                              minor(st.st_rdev)) < 0)
758                                         return -ENOMEM;
759                         } else {
760                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
761                                 return -EINVAL;
762                         }
763
764                         if (!t)
765                                 return log_oom();
766
767                         r = sd_journal_add_match(j, t, 0);
768                         if (t2)
769                                 r = sd_journal_add_match(j, t2, 0);
770                         have_term = true;
771
772                 } else {
773                         r = sd_journal_add_match(j, *i, 0);
774                         have_term = true;
775                 }
776
777                 if (r < 0) {
778                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
779                         return r;
780                 }
781         }
782
783         if (!strv_isempty(args) && !have_term) {
784                 log_error("\"+\" can only be used between terms");
785                 return -EINVAL;
786         }
787
788         return 0;
789 }
790
791 static int boot_id_cmp(const void *a, const void *b) {
792         uint64_t _a, _b;
793
794         _a = ((const boot_id_t *)a)->first;
795         _b = ((const boot_id_t *)b)->first;
796
797         return _a < _b ? -1 : (_a > _b ? 1 : 0);
798 }
799
800 static int list_boots(sd_journal *j) {
801         int r;
802         const void *data;
803         unsigned int count = 0;
804         int w, i;
805         size_t length, allocated = 0;
806         boot_id_t *id;
807         _cleanup_free_ boot_id_t *all_ids = NULL;
808
809         r = sd_journal_query_unique(j, "_BOOT_ID");
810         if (r < 0)
811                 return r;
812
813         SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
814                 if (length < strlen("_BOOT_ID="))
815                         continue;
816
817                 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
818                         return log_oom();
819
820                 id = &all_ids[count];
821
822                 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
823                 if (r < 0)
824                         continue;
825
826                 r = sd_journal_add_match(j, data, length);
827                 if (r < 0)
828                         return r;
829
830                 r = sd_journal_seek_head(j);
831                 if (r < 0)
832                         return r;
833
834                 r = sd_journal_next(j);
835                 if (r < 0)
836                         return r;
837                 else if (r == 0)
838                         goto flush;
839
840                 r = sd_journal_get_realtime_usec(j, &id->first);
841                 if (r < 0)
842                         return r;
843
844                 r = sd_journal_seek_tail(j);
845                 if (r < 0)
846                         return r;
847
848                 r = sd_journal_previous(j);
849                 if (r < 0)
850                         return r;
851                 else if (r == 0)
852                         goto flush;
853
854                 r = sd_journal_get_realtime_usec(j, &id->last);
855                 if (r < 0)
856                         return r;
857
858                 count++;
859         flush:
860                 sd_journal_flush_matches(j);
861         }
862
863         qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
864
865         /* numbers are one less, but we need an extra char for the sign */
866         w = DECIMAL_STR_WIDTH(count - 1) + 1;
867
868         for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
869                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
870
871                 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
872                        w, i - count + 1,
873                        SD_ID128_FORMAT_VAL(id->id),
874                        format_timestamp(a, sizeof(a), id->first),
875                        format_timestamp(b, sizeof(b), id->last));
876         }
877
878         return 0;
879 }
880
881 static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
882         int r;
883         const void *data;
884         unsigned int count = 0;
885         size_t length, allocated = 0;
886         boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
887         _cleanup_free_ boot_id_t *all_ids = NULL;
888
889         assert(j);
890         assert(boot_id);
891
892         r = sd_journal_query_unique(j, "_BOOT_ID");
893         if (r < 0)
894                 return r;
895
896         SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
897                 if (length < strlen("_BOOT_ID="))
898                         continue;
899
900                 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
901                         return log_oom();
902
903                 id = &all_ids[count];
904
905                 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
906                 if (r < 0)
907                         continue;
908
909                 r = sd_journal_add_match(j, data, length);
910                 if (r < 0)
911                         return r;
912
913                 r = sd_journal_seek_head(j);
914                 if (r < 0)
915                         return r;
916
917                 r = sd_journal_next(j);
918                 if (r < 0)
919                         return r;
920                 else if (r == 0)
921                         goto flush;
922
923                 r = sd_journal_get_realtime_usec(j, &id->first);
924                 if (r < 0)
925                         return r;
926
927                 if (sd_id128_equal(id->id, *boot_id))
928                         ref_boot_id = *id;
929
930                 count++;
931         flush:
932                 sd_journal_flush_matches(j);
933         }
934
935         qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
936
937         if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
938                 if (relative > (int) count || relative <= -(int)count)
939                         return -EADDRNOTAVAIL;
940
941                 *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
942         } else {
943                 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
944
945                 if (!id ||
946                     relative <= 0 ? (id - all_ids) + relative < 0 :
947                                     (id - all_ids) + relative >= (int) count)
948                         return -EADDRNOTAVAIL;
949
950                 *boot_id = (id + relative)->id;
951         }
952
953         return 0;
954 }
955
956 static int add_boot(sd_journal *j) {
957         char match[9+32+1] = "_BOOT_ID=";
958         int r;
959
960         assert(j);
961
962         if (!arg_boot)
963                 return 0;
964
965         if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
966                 return add_match_this_boot(j, arg_machine);
967
968         r = get_relative_boot_id(j, &arg_boot_id, arg_boot_offset);
969         if (r < 0) {
970                 if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
971                         log_error("Failed to look up boot %+i: %s", arg_boot_offset, strerror(-r));
972                 else
973                         log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
974                                   SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, strerror(-r));
975                 return r;
976         }
977
978         sd_id128_to_string(arg_boot_id, match + 9);
979
980         r = sd_journal_add_match(j, match, sizeof(match) - 1);
981         if (r < 0) {
982                 log_error("Failed to add match: %s", strerror(-r));
983                 return r;
984         }
985
986         r = sd_journal_add_conjunction(j);
987         if (r < 0)
988                 return r;
989
990         return 0;
991 }
992
993 static int add_dmesg(sd_journal *j) {
994         int r;
995         assert(j);
996
997         if (!arg_dmesg)
998                 return 0;
999
1000         r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1001         if (r < 0) {
1002                 log_error("Failed to add match: %s", strerror(-r));
1003                 return r;
1004         }
1005
1006         r = sd_journal_add_conjunction(j);
1007         if (r < 0)
1008                 return r;
1009
1010         return 0;
1011 }
1012
1013 static int get_possible_units(sd_journal *j,
1014                               const char *fields,
1015                               char **patterns,
1016                               Set **units) {
1017         _cleanup_set_free_free_ Set *found;
1018         const char *field;
1019         int r;
1020
1021         found = set_new(string_hash_func, string_compare_func);
1022         if (!found)
1023                 return log_oom();
1024
1025         NULSTR_FOREACH(field, fields) {
1026                 const void *data;
1027                 size_t size;
1028
1029                 r = sd_journal_query_unique(j, field);
1030                 if (r < 0)
1031                         return r;
1032
1033                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1034                         char **pattern, *eq;
1035                         size_t prefix;
1036                         _cleanup_free_ char *u = NULL;
1037
1038                         eq = memchr(data, '=', size);
1039                         if (eq)
1040                                 prefix = eq - (char*) data + 1;
1041                         else
1042                                 prefix = 0;
1043
1044                         u = strndup((char*) data + prefix, size - prefix);
1045                         if (!u)
1046                                 return log_oom();
1047
1048                         STRV_FOREACH(pattern, patterns)
1049                                 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1050                                         log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1051
1052                                         r = set_consume(found, u);
1053                                         u = NULL;
1054                                         if (r < 0 && r != -EEXIST)
1055                                                 return r;
1056
1057                                         break;
1058                                 }
1059                 }
1060         }
1061
1062         *units = found;
1063         found = NULL;
1064         return 0;
1065 }
1066
1067 /* This list is supposed to return the superset of unit names
1068  * possibly matched by rules added with add_matches_for_unit... */
1069 #define SYSTEM_UNITS                 \
1070         "_SYSTEMD_UNIT\0"            \
1071         "COREDUMP_UNIT\0"            \
1072         "UNIT\0"                     \
1073         "OBJECT_SYSTEMD_UNIT\0"      \
1074         "_SYSTEMD_SLICE\0"
1075
1076 /* ... and add_matches_for_user_unit */
1077 #define USER_UNITS                   \
1078         "_SYSTEMD_USER_UNIT\0"       \
1079         "USER_UNIT\0"                \
1080         "COREDUMP_USER_UNIT\0"       \
1081         "OBJECT_SYSTEMD_USER_UNIT\0"
1082
1083 static int add_units(sd_journal *j) {
1084         _cleanup_strv_free_ char **patterns = NULL;
1085         int r, count = 0;
1086         char **i;
1087
1088         assert(j);
1089
1090         STRV_FOREACH(i, arg_system_units) {
1091                 _cleanup_free_ char *u = NULL;
1092
1093                 u = unit_name_mangle(*i, MANGLE_GLOB);
1094                 if (!u)
1095                         return log_oom();
1096
1097                 if (string_is_glob(u)) {
1098                         r = strv_push(&patterns, u);
1099                         if (r < 0)
1100                                 return r;
1101                         u = NULL;
1102                 } else {
1103                         r = add_matches_for_unit(j, u);
1104                         if (r < 0)
1105                                 return r;
1106                         r = sd_journal_add_disjunction(j);
1107                         if (r < 0)
1108                                 return r;
1109                         count ++;
1110                 }
1111         }
1112
1113         if (!strv_isempty(patterns)) {
1114                 _cleanup_set_free_free_ Set *units = NULL;
1115                 Iterator it;
1116                 char *u;
1117
1118                 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1119                 if (r < 0)
1120                         return r;
1121
1122                 SET_FOREACH(u, units, it) {
1123                         r = add_matches_for_unit(j, u);
1124                         if (r < 0)
1125                                 return r;
1126                         r = sd_journal_add_disjunction(j);
1127                         if (r < 0)
1128                                 return r;
1129                         count ++;
1130                 }
1131         }
1132
1133         strv_free(patterns);
1134         patterns = NULL;
1135
1136         STRV_FOREACH(i, arg_user_units) {
1137                 _cleanup_free_ char *u = NULL;
1138
1139                 u = unit_name_mangle(*i, MANGLE_GLOB);
1140                 if (!u)
1141                         return log_oom();
1142
1143                 if (string_is_glob(u)) {
1144                         r = strv_push(&patterns, u);
1145                         if (r < 0)
1146                                 return r;
1147                         u = NULL;
1148                 } else {
1149                         r = add_matches_for_user_unit(j, u, getuid());
1150                         if (r < 0)
1151                                 return r;
1152                         r = sd_journal_add_disjunction(j);
1153                         if (r < 0)
1154                                 return r;
1155                         count ++;
1156                 }
1157         }
1158
1159         if (!strv_isempty(patterns)) {
1160                 _cleanup_set_free_free_ Set *units = NULL;
1161                 Iterator it;
1162                 char *u;
1163
1164                 r = get_possible_units(j, USER_UNITS, patterns, &units);
1165                 if (r < 0)
1166                         return r;
1167
1168                 SET_FOREACH(u, units, it) {
1169                         r = add_matches_for_user_unit(j, u, getuid());
1170                         if (r < 0)
1171                                 return r;
1172                         r = sd_journal_add_disjunction(j);
1173                         if (r < 0)
1174                                 return r;
1175                         count ++;
1176                 }
1177         }
1178
1179         /* Complain if the user request matches but nothing whatsoever was
1180          * found, since otherwise everything would be matched. */
1181         if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1182                 return -ENODATA;
1183
1184         r = sd_journal_add_conjunction(j);
1185         if (r < 0)
1186                 return r;
1187
1188         return 0;
1189 }
1190
1191 static int add_priorities(sd_journal *j) {
1192         char match[] = "PRIORITY=0";
1193         int i, r;
1194         assert(j);
1195
1196         if (arg_priorities == 0xFF)
1197                 return 0;
1198
1199         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1200                 if (arg_priorities & (1 << i)) {
1201                         match[sizeof(match)-2] = '0' + i;
1202
1203                         r = sd_journal_add_match(j, match, strlen(match));
1204                         if (r < 0) {
1205                                 log_error("Failed to add match: %s", strerror(-r));
1206                                 return r;
1207                         }
1208                 }
1209
1210         r = sd_journal_add_conjunction(j);
1211         if (r < 0)
1212                 return r;
1213
1214         return 0;
1215 }
1216
1217 static int setup_keys(void) {
1218 #ifdef HAVE_GCRYPT
1219         size_t mpk_size, seed_size, state_size, i;
1220         uint8_t *mpk, *seed, *state;
1221         ssize_t l;
1222         int fd = -1, r, attr = 0;
1223         sd_id128_t machine, boot;
1224         char *p = NULL, *k = NULL;
1225         struct FSSHeader h;
1226         uint64_t n;
1227         struct stat st;
1228
1229         r = stat("/var/log/journal", &st);
1230         if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
1231                 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
1232                 return -errno;
1233         }
1234
1235         if (r < 0 || !S_ISDIR(st.st_mode)) {
1236                 log_error("%s is not a directory, must be using persistent logging for FSS.",
1237                           "/var/log/journal");
1238                 return r < 0 ? -errno : -ENOTDIR;
1239         }
1240
1241         r = sd_id128_get_machine(&machine);
1242         if (r < 0) {
1243                 log_error("Failed to get machine ID: %s", strerror(-r));
1244                 return r;
1245         }
1246
1247         r = sd_id128_get_boot(&boot);
1248         if (r < 0) {
1249                 log_error("Failed to get boot ID: %s", strerror(-r));
1250                 return r;
1251         }
1252
1253         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1254                      SD_ID128_FORMAT_VAL(machine)) < 0)
1255                 return log_oom();
1256
1257         if (access(p, F_OK) >= 0) {
1258                 if (arg_force) {
1259                         r = unlink(p);
1260                         if (r < 0) {
1261                                 log_error("unlink(\"%s\") failed: %m", p);
1262                                 r = -errno;
1263                                 goto finish;
1264                         }
1265                 } else {
1266                         log_error("Sealing key file %s exists already. (--force to recreate)", p);
1267                         r = -EEXIST;
1268                         goto finish;
1269                 }
1270         }
1271
1272         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1273                      SD_ID128_FORMAT_VAL(machine)) < 0) {
1274                 r = log_oom();
1275                 goto finish;
1276         }
1277
1278         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1279         mpk = alloca(mpk_size);
1280
1281         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1282         seed = alloca(seed_size);
1283
1284         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1285         state = alloca(state_size);
1286
1287         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1288         if (fd < 0) {
1289                 log_error("Failed to open /dev/random: %m");
1290                 r = -errno;
1291                 goto finish;
1292         }
1293
1294         log_info("Generating seed...");
1295         l = loop_read(fd, seed, seed_size, true);
1296         if (l < 0 || (size_t) l != seed_size) {
1297                 log_error("Failed to read random seed: %s", strerror(EIO));
1298                 r = -EIO;
1299                 goto finish;
1300         }
1301
1302         log_info("Generating key pair...");
1303         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1304
1305         log_info("Generating sealing key...");
1306         FSPRG_GenState0(state, mpk, seed, seed_size);
1307
1308         assert(arg_interval > 0);
1309
1310         n = now(CLOCK_REALTIME);
1311         n /= arg_interval;
1312
1313         safe_close(fd);
1314         fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1315         if (fd < 0) {
1316                 log_error("Failed to open %s: %m", k);
1317                 r = -errno;
1318                 goto finish;
1319         }
1320
1321         /* Enable secure remove, exclusion from dump, synchronous
1322          * writing and in-place updating */
1323         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
1324                 log_warning("FS_IOC_GETFLAGS failed: %m");
1325
1326         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1327
1328         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1329                 log_warning("FS_IOC_SETFLAGS failed: %m");
1330
1331         zero(h);
1332         memcpy(h.signature, "KSHHRHLP", 8);
1333         h.machine_id = machine;
1334         h.boot_id = boot;
1335         h.header_size = htole64(sizeof(h));
1336         h.start_usec = htole64(n * arg_interval);
1337         h.interval_usec = htole64(arg_interval);
1338         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1339         h.fsprg_state_size = htole64(state_size);
1340
1341         l = loop_write(fd, &h, sizeof(h), false);
1342         if (l < 0 || (size_t) l != sizeof(h)) {
1343                 log_error("Failed to write header: %s", strerror(EIO));
1344                 r = -EIO;
1345                 goto finish;
1346         }
1347
1348         l = loop_write(fd, state, state_size, false);
1349         if (l < 0 || (size_t) l != state_size) {
1350                 log_error("Failed to write state: %s", strerror(EIO));
1351                 r = -EIO;
1352                 goto finish;
1353         }
1354
1355         if (link(k, p) < 0) {
1356                 log_error("Failed to link file: %m");
1357                 r = -errno;
1358                 goto finish;
1359         }
1360
1361         if (on_tty()) {
1362                 fprintf(stderr,
1363                         "\n"
1364                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
1365                         "the following local file. This key file is automatically updated when the\n"
1366                         "sealing key is advanced. It should not be used on multiple hosts.\n"
1367                         "\n"
1368                         "\t%s\n"
1369                         "\n"
1370                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
1371                         "at a safe location and should not be saved locally on disk.\n"
1372                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
1373                 fflush(stderr);
1374         }
1375         for (i = 0; i < seed_size; i++) {
1376                 if (i > 0 && i % 3 == 0)
1377                         putchar('-');
1378                 printf("%02x", ((uint8_t*) seed)[i]);
1379         }
1380
1381         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1382
1383         if (on_tty()) {
1384                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1385
1386                 fprintf(stderr,
1387                         ANSI_HIGHLIGHT_OFF "\n"
1388                         "The sealing key is automatically changed every %s.\n",
1389                         format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1390
1391                 hn = gethostname_malloc();
1392
1393                 if (hn) {
1394                         hostname_cleanup(hn, false);
1395                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1396                 } else
1397                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1398
1399 #ifdef HAVE_QRENCODE
1400                 /* If this is not an UTF-8 system don't print any QR codes */
1401                 if (is_locale_utf8()) {
1402                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1403                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1404                 }
1405 #endif
1406                 free(hn);
1407         }
1408
1409         r = 0;
1410
1411 finish:
1412         safe_close(fd);
1413
1414         if (k) {
1415                 unlink(k);
1416                 free(k);
1417         }
1418
1419         free(p);
1420
1421         return r;
1422 #else
1423         log_error("Forward-secure sealing not available.");
1424         return -ENOTSUP;
1425 #endif
1426 }
1427
1428 static int verify(sd_journal *j) {
1429         int r = 0;
1430         Iterator i;
1431         JournalFile *f;
1432
1433         assert(j);
1434
1435         log_show_color(true);
1436
1437         HASHMAP_FOREACH(f, j->files, i) {
1438                 int k;
1439                 usec_t first, validated, last;
1440
1441 #ifdef HAVE_GCRYPT
1442                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1443                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1444 #endif
1445
1446                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1447                 if (k == -EINVAL) {
1448                         /* If the key was invalid give up right-away. */
1449                         return k;
1450                 } else if (k < 0) {
1451                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1452                         r = k;
1453                 } else {
1454                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1455                         log_info("PASS: %s", f->path);
1456
1457                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1458                                 if (validated > 0) {
1459                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
1460                                                  format_timestamp(a, sizeof(a), first),
1461                                                  format_timestamp(b, sizeof(b), validated),
1462                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1463                                 } else if (last > 0)
1464                                         log_info("=> No sealing yet, %s of entries not sealed.",
1465                                                  format_timespan(c, sizeof(c), last - first, 0));
1466                                 else
1467                                         log_info("=> No sealing yet, no entries in file.");
1468                         }
1469                 }
1470         }
1471
1472         return r;
1473 }
1474
1475 #ifdef HAVE_ACL
1476 static int access_check_var_log_journal(sd_journal *j) {
1477         _cleanup_strv_free_ char **g = NULL;
1478         bool have_access;
1479         int r;
1480
1481         assert(j);
1482
1483         have_access = in_group("systemd-journal") > 0;
1484
1485         if (!have_access) {
1486                 /* Let's enumerate all groups from the default ACL of
1487                  * the directory, which generally should allow access
1488                  * to most journal files too */
1489                 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1490                 if (r < 0)
1491                         return r;
1492         }
1493
1494         if (!have_access) {
1495
1496                 if (strv_isempty(g))
1497                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1498                                    "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1499                                    "      turn off this notice.");
1500                 else {
1501                         _cleanup_free_ char *s = NULL;
1502
1503                         r = strv_extend(&g, "systemd-journal");
1504                         if (r < 0)
1505                                 return log_oom();
1506
1507                         strv_sort(g);
1508                         strv_uniq(g);
1509
1510                         s = strv_join(g, "', '");
1511                         if (!s)
1512                                 return log_oom();
1513
1514                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1515                                    "      Users in the groups '%s' can see all messages.\n"
1516                                    "      Pass -q to turn off this notice.", s);
1517                 }
1518         }
1519
1520         return 0;
1521 }
1522 #endif
1523
1524 static int access_check(sd_journal *j) {
1525         Iterator it;
1526         void *code;
1527         int r = 0;
1528
1529         assert(j);
1530
1531         if (set_isempty(j->errors)) {
1532                 if (hashmap_isempty(j->files))
1533                         log_notice("No journal files were found.");
1534                 return 0;
1535         }
1536
1537         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1538 #ifdef HAVE_ACL
1539                 /* If /var/log/journal doesn't even exist,
1540                  * unprivileged users have no access at all */
1541                 if (access("/var/log/journal", F_OK) < 0 &&
1542                     geteuid() != 0 &&
1543                     in_group("systemd-journal") <= 0) {
1544                         log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1545                                   "enabled. Users in the 'systemd-journal' group may always access messages.");
1546                         return -EACCES;
1547                 }
1548
1549                 /* If /var/log/journal exists, try to pring a nice
1550                    notice if the user lacks access to it */
1551                 if (!arg_quiet && geteuid() != 0) {
1552                         r = access_check_var_log_journal(j);
1553                         if (r < 0)
1554                                 return r;
1555                 }
1556 #else
1557                 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1558                         log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1559                                   "group may access messages.");
1560                         return -EACCES;
1561                 }
1562 #endif
1563
1564                 if (hashmap_isempty(j->files)) {
1565                         log_error("No journal files were opened due to insufficient permissions.");
1566                         r = -EACCES;
1567                 }
1568         }
1569
1570         SET_FOREACH(code, j->errors, it) {
1571                 int err;
1572
1573                 err = -PTR_TO_INT(code);
1574                 assert(err > 0);
1575
1576                 if (err != EACCES)
1577                         log_warning("Error was encountered while opening journal files: %s",
1578                                     strerror(err));
1579         }
1580
1581         return r;
1582 }
1583
1584 int main(int argc, char *argv[]) {
1585         int r;
1586         _cleanup_journal_close_ sd_journal *j = NULL;
1587         bool need_seek = false;
1588         sd_id128_t previous_boot_id;
1589         bool previous_boot_id_valid = false, first_line = true;
1590         int n_shown = 0;
1591         bool ellipsized = false;
1592
1593         setlocale(LC_ALL, "");
1594         log_parse_environment();
1595         log_open();
1596
1597         r = parse_argv(argc, argv);
1598         if (r <= 0)
1599                 goto finish;
1600
1601         signal(SIGWINCH, columns_lines_cache_reset);
1602
1603         if (arg_action == ACTION_NEW_ID128) {
1604                 r = generate_new_id128();
1605                 goto finish;
1606         }
1607
1608         if (arg_action == ACTION_SETUP_KEYS) {
1609                 r = setup_keys();
1610                 goto finish;
1611         }
1612
1613         if (arg_action == ACTION_UPDATE_CATALOG ||
1614             arg_action == ACTION_LIST_CATALOG ||
1615             arg_action == ACTION_DUMP_CATALOG) {
1616
1617                 _cleanup_free_ char *database;
1618
1619                 database = path_join(arg_root, CATALOG_DATABASE, NULL);
1620                 if (!database) {
1621                         r = log_oom();
1622                         goto finish;
1623                 }
1624
1625                 if (arg_action == ACTION_UPDATE_CATALOG) {
1626                         r = catalog_update(database, arg_root, catalog_file_dirs);
1627                         if (r < 0)
1628                                 log_error("Failed to list catalog: %s", strerror(-r));
1629                 } else {
1630                         bool oneline = arg_action == ACTION_LIST_CATALOG;
1631
1632                         if (optind < argc)
1633                                 r = catalog_list_items(stdout, database,
1634                                                        oneline, argv + optind);
1635                         else
1636                                 r = catalog_list(stdout, database, oneline);
1637                         if (r < 0)
1638                                 log_error("Failed to list catalog: %s", strerror(-r));
1639                 }
1640
1641                 goto finish;
1642         }
1643
1644         if (arg_directory)
1645                 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1646         else if (arg_file)
1647                 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1648         else if (arg_machine)
1649                 r = sd_journal_open_container(&j, arg_machine, 0);
1650         else
1651                 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1652         if (r < 0) {
1653                 log_error("Failed to open %s: %s",
1654                           arg_directory ? arg_directory : arg_file ? "files" : "journal",
1655                           strerror(-r));
1656                 return EXIT_FAILURE;
1657         }
1658
1659         r = access_check(j);
1660         if (r < 0)
1661                 return EXIT_FAILURE;
1662
1663         if (arg_action == ACTION_VERIFY) {
1664                 r = verify(j);
1665                 goto finish;
1666         }
1667
1668         if (arg_action == ACTION_PRINT_HEADER) {
1669                 journal_print_header(j);
1670                 return EXIT_SUCCESS;
1671         }
1672
1673         if (arg_action == ACTION_DISK_USAGE) {
1674                 uint64_t bytes = 0;
1675                 char sbytes[FORMAT_BYTES_MAX];
1676
1677                 r = sd_journal_get_usage(j, &bytes);
1678                 if (r < 0)
1679                         return EXIT_FAILURE;
1680
1681                 printf("Journals take up %s on disk.\n",
1682                        format_bytes(sbytes, sizeof(sbytes), bytes));
1683                 return EXIT_SUCCESS;
1684         }
1685
1686         if (arg_action == ACTION_LIST_BOOTS) {
1687                 r = list_boots(j);
1688                 goto finish;
1689         }
1690
1691         /* add_boot() must be called first!
1692          * It may need to seek the journal to find parent boot IDs. */
1693         r = add_boot(j);
1694         if (r < 0)
1695                 return EXIT_FAILURE;
1696
1697         r = add_dmesg(j);
1698         if (r < 0)
1699                 return EXIT_FAILURE;
1700
1701         r = add_units(j);
1702         strv_free(arg_system_units);
1703         strv_free(arg_user_units);
1704
1705         if (r < 0) {
1706                 log_error("Failed to add filter for units: %s", strerror(-r));
1707                 return EXIT_FAILURE;
1708         }
1709
1710         r = add_priorities(j);
1711         if (r < 0) {
1712                 log_error("Failed to add filter for priorities: %s", strerror(-r));
1713                 return EXIT_FAILURE;
1714         }
1715
1716         r = add_matches(j, argv + optind);
1717         if (r < 0) {
1718                 log_error("Failed to add filters: %s", strerror(-r));
1719                 return EXIT_FAILURE;
1720         }
1721
1722         if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1723                 _cleanup_free_ char *filter;
1724
1725                 filter = journal_make_match_string(j);
1726                 log_debug("Journal filter: %s", filter);
1727         }
1728
1729         if (arg_field) {
1730                 const void *data;
1731                 size_t size;
1732
1733                 r = sd_journal_set_data_threshold(j, 0);
1734                 if (r < 0) {
1735                         log_error("Failed to unset data size threshold");
1736                         return EXIT_FAILURE;
1737                 }
1738
1739                 r = sd_journal_query_unique(j, arg_field);
1740                 if (r < 0) {
1741                         log_error("Failed to query unique data objects: %s", strerror(-r));
1742                         return EXIT_FAILURE;
1743                 }
1744
1745                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1746                         const void *eq;
1747
1748                         if (arg_lines >= 0 && n_shown >= arg_lines)
1749                                 break;
1750
1751                         eq = memchr(data, '=', size);
1752                         if (eq)
1753                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1754                         else
1755                                 printf("%.*s\n", (int) size, (const char*) data);
1756
1757                         n_shown ++;
1758                 }
1759
1760                 return EXIT_SUCCESS;
1761         }
1762
1763         /* Opening the fd now means the first sd_journal_wait() will actually wait */
1764         if (arg_follow) {
1765                 r = sd_journal_get_fd(j);
1766                 if (r < 0)
1767                         return EXIT_FAILURE;
1768         }
1769
1770         if (arg_cursor || arg_after_cursor) {
1771                 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
1772                 if (r < 0) {
1773                         log_error("Failed to seek to cursor: %s", strerror(-r));
1774                         return EXIT_FAILURE;
1775                 }
1776                 if (!arg_reverse)
1777                         r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1778                 else
1779                         r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1780
1781                 if (arg_after_cursor && r < 2 && !arg_follow)
1782                         /* We couldn't find the next entry after the cursor. */
1783                         arg_lines = 0;
1784
1785         } else if (arg_since_set && !arg_reverse) {
1786                 r = sd_journal_seek_realtime_usec(j, arg_since);
1787                 if (r < 0) {
1788                         log_error("Failed to seek to date: %s", strerror(-r));
1789                         return EXIT_FAILURE;
1790                 }
1791                 r = sd_journal_next(j);
1792
1793         } else if (arg_until_set && arg_reverse) {
1794                 r = sd_journal_seek_realtime_usec(j, arg_until);
1795                 if (r < 0) {
1796                         log_error("Failed to seek to date: %s", strerror(-r));
1797                         return EXIT_FAILURE;
1798                 }
1799                 r = sd_journal_previous(j);
1800
1801         } else if (arg_lines >= 0) {
1802                 r = sd_journal_seek_tail(j);
1803                 if (r < 0) {
1804                         log_error("Failed to seek to tail: %s", strerror(-r));
1805                         return EXIT_FAILURE;
1806                 }
1807
1808                 r = sd_journal_previous_skip(j, arg_lines);
1809
1810         } else if (arg_reverse) {
1811                 r = sd_journal_seek_tail(j);
1812                 if (r < 0) {
1813                         log_error("Failed to seek to tail: %s", strerror(-r));
1814                         return EXIT_FAILURE;
1815                 }
1816
1817                 r = sd_journal_previous(j);
1818
1819         } else {
1820                 r = sd_journal_seek_head(j);
1821                 if (r < 0) {
1822                         log_error("Failed to seek to head: %s", strerror(-r));
1823                         return EXIT_FAILURE;
1824                 }
1825
1826                 r = sd_journal_next(j);
1827         }
1828
1829         if (r < 0) {
1830                 log_error("Failed to iterate through journal: %s", strerror(-r));
1831                 return EXIT_FAILURE;
1832         }
1833
1834         if (!arg_follow)
1835                 pager_open_if_enabled();
1836
1837         if (!arg_quiet) {
1838                 usec_t start, end;
1839                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1840
1841                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1842                 if (r < 0) {
1843                         log_error("Failed to get cutoff: %s", strerror(-r));
1844                         goto finish;
1845                 }
1846
1847                 if (r > 0) {
1848                         if (arg_follow)
1849                                 printf("-- Logs begin at %s. --\n",
1850                                        format_timestamp(start_buf, sizeof(start_buf), start));
1851                         else
1852                                 printf("-- Logs begin at %s, end at %s. --\n",
1853                                        format_timestamp(start_buf, sizeof(start_buf), start),
1854                                        format_timestamp(end_buf, sizeof(end_buf), end));
1855                 }
1856         }
1857
1858         for (;;) {
1859                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1860                         int flags;
1861
1862                         if (need_seek) {
1863                                 if (!arg_reverse)
1864                                         r = sd_journal_next(j);
1865                                 else
1866                                         r = sd_journal_previous(j);
1867                                 if (r < 0) {
1868                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1869                                         goto finish;
1870                                 }
1871                                 if (r == 0)
1872                                         break;
1873                         }
1874
1875                         if (arg_until_set && !arg_reverse) {
1876                                 usec_t usec;
1877
1878                                 r = sd_journal_get_realtime_usec(j, &usec);
1879                                 if (r < 0) {
1880                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1881                                         goto finish;
1882                                 }
1883                                 if (usec > arg_until)
1884                                         goto finish;
1885                         }
1886
1887                         if (arg_since_set && arg_reverse) {
1888                                 usec_t usec;
1889
1890                                 r = sd_journal_get_realtime_usec(j, &usec);
1891                                 if (r < 0) {
1892                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1893                                         goto finish;
1894                                 }
1895                                 if (usec < arg_since)
1896                                         goto finish;
1897                         }
1898
1899                         if (!arg_merge) {
1900                                 sd_id128_t boot_id;
1901
1902                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1903                                 if (r >= 0) {
1904                                         if (previous_boot_id_valid &&
1905                                             !sd_id128_equal(boot_id, previous_boot_id))
1906                                                 printf("%s-- Reboot --%s\n",
1907                                                        ansi_highlight(), ansi_highlight_off());
1908
1909                                         previous_boot_id = boot_id;
1910                                         previous_boot_id_valid = true;
1911                                 }
1912                         }
1913
1914                         flags =
1915                                 arg_all * OUTPUT_SHOW_ALL |
1916                                 arg_full * OUTPUT_FULL_WIDTH |
1917                                 on_tty() * OUTPUT_COLOR |
1918                                 arg_catalog * OUTPUT_CATALOG;
1919
1920                         r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
1921                         need_seek = true;
1922                         if (r == -EADDRNOTAVAIL)
1923                                 break;
1924                         else if (r < 0 || ferror(stdout))
1925                                 goto finish;
1926
1927                         n_shown++;
1928                 }
1929
1930                 if (!arg_follow) {
1931                         if (arg_show_cursor) {
1932                                 _cleanup_free_ char *cursor = NULL;
1933
1934                                 r = sd_journal_get_cursor(j, &cursor);
1935                                 if (r < 0 && r != -EADDRNOTAVAIL)
1936                                         log_error("Failed to get cursor: %s", strerror(-r));
1937                                 else if (r >= 0)
1938                                         printf("-- cursor: %s\n", cursor);
1939                         }
1940
1941                         break;
1942                 }
1943
1944                 r = sd_journal_wait(j, (uint64_t) -1);
1945                 if (r < 0) {
1946                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1947                         goto finish;
1948                 }
1949
1950                 first_line = false;
1951         }
1952
1953 finish:
1954         pager_close();
1955
1956         strv_free(arg_file);
1957
1958         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1959 }