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