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