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