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