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