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