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