chiark / gitweb /
man/sd_journal_next: fix argument in example
[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 only the system journal\n"
171                "     --user                Show only 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
703         assert(j);
704
705         STRV_FOREACH(i, args) {
706                 int r;
707
708                 if (streq(*i, "+"))
709                         r = sd_journal_add_disjunction(j);
710                 else if (path_is_absolute(*i)) {
711                         _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
712                         const char *path;
713                         _cleanup_free_ char *interpreter = NULL;
714                         struct stat st;
715
716                         p = canonicalize_file_name(*i);
717                         path = p ? p : *i;
718
719                         if (stat(path, &st) < 0)  {
720                                 log_error("Couldn't stat file: %m");
721                                 return -errno;
722                         }
723
724                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
725                                 if (executable_is_script(path, &interpreter) > 0) {
726                                         _cleanup_free_ char *comm;
727
728                                         comm = strndup(basename(path), 15);
729                                         if (!comm)
730                                                 return log_oom();
731
732                                         t = strappend("_COMM=", comm);
733
734                                         /* Append _EXE only if the interpreter is not a link.
735                                            Otherwise, it might be outdated often. */
736                                         if (lstat(interpreter, &st) == 0 &&
737                                             !S_ISLNK(st.st_mode)) {
738                                                 t2 = strappend("_EXE=", interpreter);
739                                                 if (!t2)
740                                                         return log_oom();
741                                         }
742                                 } else
743                                         t = strappend("_EXE=", path);
744                         } else if (S_ISCHR(st.st_mode))
745                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
746                         else if (S_ISBLK(st.st_mode))
747                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
748                         else {
749                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
750                                 return -EINVAL;
751                         }
752
753                         if (!t)
754                                 return log_oom();
755
756                         r = sd_journal_add_match(j, t, 0);
757                         if (t2)
758                                 r = sd_journal_add_match(j, t2, 0);
759                 } else
760                         r = sd_journal_add_match(j, *i, 0);
761
762                 if (r < 0) {
763                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
764                         return r;
765                 }
766         }
767
768         return 0;
769 }
770
771 static int boot_id_cmp(const void *a, const void *b) {
772         uint64_t _a, _b;
773
774         _a = ((const boot_id_t *)a)->first;
775         _b = ((const boot_id_t *)b)->first;
776
777         return _a < _b ? -1 : (_a > _b ? 1 : 0);
778 }
779
780 static int list_boots(sd_journal *j) {
781         int r;
782         const void *data;
783         unsigned int count = 0;
784         int w, i;
785         size_t length, allocated = 0;
786         boot_id_t *id;
787         _cleanup_free_ boot_id_t *all_ids = NULL;
788
789         r = sd_journal_query_unique(j, "_BOOT_ID");
790         if (r < 0)
791                 return r;
792
793         SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
794                 if (length < strlen("_BOOT_ID="))
795                         continue;
796
797                 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
798                         return log_oom();
799
800                 id = &all_ids[count];
801
802                 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
803                 if (r < 0)
804                         continue;
805
806                 r = sd_journal_add_match(j, data, length);
807                 if (r < 0)
808                         return r;
809
810                 r = sd_journal_seek_head(j);
811                 if (r < 0)
812                         return r;
813
814                 r = sd_journal_next(j);
815                 if (r < 0)
816                         return r;
817                 else if (r == 0)
818                         goto flush;
819
820                 r = sd_journal_get_realtime_usec(j, &id->first);
821                 if (r < 0)
822                         return r;
823
824                 r = sd_journal_seek_tail(j);
825                 if (r < 0)
826                         return r;
827
828                 r = sd_journal_previous(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->last);
835                 if (r < 0)
836                         return r;
837
838                 count++;
839         flush:
840                 sd_journal_flush_matches(j);
841         }
842
843         qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
844
845         /* numbers are one less, but we need an extra char for the sign */
846         w = DECIMAL_STR_WIDTH(count - 1) + 1;
847
848         for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
849                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
850
851                 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
852                        w, i - count + 1,
853                        SD_ID128_FORMAT_VAL(id->id),
854                        format_timestamp(a, sizeof(a), id->first),
855                        format_timestamp(b, sizeof(b), id->last));
856         }
857
858         return 0;
859 }
860
861 static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
862         int r;
863         const void *data;
864         unsigned int count = 0;
865         size_t length, allocated = 0;
866         boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
867         _cleanup_free_ boot_id_t *all_ids = NULL;
868
869         assert(j);
870         assert(boot_id);
871
872         r = sd_journal_query_unique(j, "_BOOT_ID");
873         if (r < 0)
874                 return r;
875
876         SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
877                 if (length < strlen("_BOOT_ID="))
878                         continue;
879
880                 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
881                         return log_oom();
882
883                 id = &all_ids[count];
884
885                 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
886                 if (r < 0)
887                         continue;
888
889                 r = sd_journal_add_match(j, data, length);
890                 if (r < 0)
891                         return r;
892
893                 r = sd_journal_seek_head(j);
894                 if (r < 0)
895                         return r;
896
897                 r = sd_journal_next(j);
898                 if (r < 0)
899                         return r;
900                 else if (r == 0)
901                         goto flush;
902
903                 r = sd_journal_get_realtime_usec(j, &id->first);
904                 if (r < 0)
905                         return r;
906
907                 if (sd_id128_equal(id->id, *boot_id))
908                         ref_boot_id = *id;
909
910                 count++;
911         flush:
912                 sd_journal_flush_matches(j);
913         }
914
915         qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
916
917         if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
918                 if (relative > (int) count || relative <= -(int)count)
919                         return -EADDRNOTAVAIL;
920
921                 *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
922         } else {
923                 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
924
925                 if (!id ||
926                     relative <= 0 ? (id - all_ids) + relative < 0 :
927                                     (id - all_ids) + relative >= (int) count)
928                         return -EADDRNOTAVAIL;
929
930                 *boot_id = (id + relative)->id;
931         }
932
933         return 0;
934 }
935
936 static int add_boot(sd_journal *j) {
937         char match[9+32+1] = "_BOOT_ID=";
938         int r;
939
940         assert(j);
941
942         if (!arg_boot)
943                 return 0;
944
945         if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
946                 return add_match_this_boot(j, arg_machine);
947
948         r = get_relative_boot_id(j, &arg_boot_id, arg_boot_offset);
949         if (r < 0) {
950                 if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
951                         log_error("Failed to look up boot %+i: %s", arg_boot_offset, strerror(-r));
952                 else
953                         log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
954                                   SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, strerror(-r));
955                 return r;
956         }
957
958         sd_id128_to_string(arg_boot_id, match + 9);
959
960         r = sd_journal_add_match(j, match, sizeof(match) - 1);
961         if (r < 0) {
962                 log_error("Failed to add match: %s", strerror(-r));
963                 return r;
964         }
965
966         r = sd_journal_add_conjunction(j);
967         if (r < 0)
968                 return r;
969
970         return 0;
971 }
972
973 static int add_dmesg(sd_journal *j) {
974         int r;
975         assert(j);
976
977         if (!arg_dmesg)
978                 return 0;
979
980         r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
981         if (r < 0) {
982                 log_error("Failed to add match: %s", strerror(-r));
983                 return r;
984         }
985
986         r = sd_journal_add_conjunction(j);
987         if (r < 0)
988                 return r;
989
990         return 0;
991 }
992
993 static int get_possible_units(sd_journal *j,
994                               const char *fields,
995                               char **patterns,
996                               Set **units) {
997         _cleanup_set_free_free_ Set *found;
998         const char *field;
999         int r;
1000
1001         found = set_new(string_hash_func, string_compare_func);
1002         if (!found)
1003                 return log_oom();
1004
1005         NULSTR_FOREACH(field, fields) {
1006                 const void *data;
1007                 size_t size;
1008
1009                 r = sd_journal_query_unique(j, field);
1010                 if (r < 0)
1011                         return r;
1012
1013                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1014                         char **pattern, *eq;
1015                         size_t prefix;
1016                         _cleanup_free_ char *u = NULL;
1017
1018                         eq = memchr(data, '=', size);
1019                         if (eq)
1020                                 prefix = eq - (char*) data + 1;
1021                         else
1022                                 prefix = 0;
1023
1024                         u = strndup((char*) data + prefix, size - prefix);
1025                         if (!u)
1026                                 return log_oom();
1027
1028                         STRV_FOREACH(pattern, patterns)
1029                                 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1030                                         log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1031
1032                                         r = set_consume(found, u);
1033                                         u = NULL;
1034                                         if (r < 0 && r != -EEXIST)
1035                                                 return r;
1036
1037                                         break;
1038                                 }
1039                 }
1040         }
1041
1042         *units = found;
1043         found = NULL;
1044         return 0;
1045 }
1046
1047 /* This list is supposed to return the superset of unit names
1048  * possibly matched by rules added with add_matches_for_unit... */
1049 #define SYSTEM_UNITS                 \
1050         "_SYSTEMD_UNIT\0"            \
1051         "COREDUMP_UNIT\0"            \
1052         "UNIT\0"                     \
1053         "OBJECT_SYSTEMD_UNIT\0"      \
1054         "_SYSTEMD_SLICE\0"
1055
1056 /* ... and add_matches_for_user_unit */
1057 #define USER_UNITS                   \
1058         "_SYSTEMD_USER_UNIT\0"       \
1059         "USER_UNIT\0"                \
1060         "COREDUMP_USER_UNIT\0"       \
1061         "OBJECT_SYSTEMD_USER_UNIT\0"
1062
1063 static int add_units(sd_journal *j) {
1064         _cleanup_strv_free_ char **patterns = NULL;
1065         int r, count = 0;
1066         char **i;
1067
1068         assert(j);
1069
1070         STRV_FOREACH(i, arg_system_units) {
1071                 _cleanup_free_ char *u = NULL;
1072
1073                 u = unit_name_mangle(*i, MANGLE_GLOB);
1074                 if (!u)
1075                         return log_oom();
1076
1077                 if (string_is_glob(u)) {
1078                         r = strv_push(&patterns, u);
1079                         if (r < 0)
1080                                 return r;
1081                         u = NULL;
1082                 } else {
1083                         r = add_matches_for_unit(j, u);
1084                         if (r < 0)
1085                                 return r;
1086                         r = sd_journal_add_disjunction(j);
1087                         if (r < 0)
1088                                 return r;
1089                         count ++;
1090                 }
1091         }
1092
1093         if (!strv_isempty(patterns)) {
1094                 _cleanup_set_free_free_ Set *units = NULL;
1095                 Iterator it;
1096                 char *u;
1097
1098                 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1099                 if (r < 0)
1100                         return r;
1101
1102                 SET_FOREACH(u, units, it) {
1103                         r = add_matches_for_unit(j, u);
1104                         if (r < 0)
1105                                 return r;
1106                         r = sd_journal_add_disjunction(j);
1107                         if (r < 0)
1108                                 return r;
1109                         count ++;
1110                 }
1111         }
1112
1113         strv_free(patterns);
1114         patterns = NULL;
1115
1116         STRV_FOREACH(i, arg_user_units) {
1117                 _cleanup_free_ char *u = NULL;
1118
1119                 u = unit_name_mangle(*i, MANGLE_GLOB);
1120                 if (!u)
1121                         return log_oom();
1122
1123                 if (string_is_glob(u)) {
1124                         r = strv_push(&patterns, u);
1125                         if (r < 0)
1126                                 return r;
1127                         u = NULL;
1128                 } else {
1129                         r = add_matches_for_user_unit(j, u, getuid());
1130                         if (r < 0)
1131                                 return r;
1132                         r = sd_journal_add_disjunction(j);
1133                         if (r < 0)
1134                                 return r;
1135                         count ++;
1136                 }
1137         }
1138
1139         if (!strv_isempty(patterns)) {
1140                 _cleanup_set_free_free_ Set *units = NULL;
1141                 Iterator it;
1142                 char *u;
1143
1144                 r = get_possible_units(j, USER_UNITS, patterns, &units);
1145                 if (r < 0)
1146                         return r;
1147
1148                 SET_FOREACH(u, units, it) {
1149                         r = add_matches_for_user_unit(j, u, getuid());
1150                         if (r < 0)
1151                                 return r;
1152                         r = sd_journal_add_disjunction(j);
1153                         if (r < 0)
1154                                 return r;
1155                         count ++;
1156                 }
1157         }
1158
1159         /* Complain if the user request matches but nothing whatsoever was
1160          * found, since otherwise everything would be matched. */
1161         if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1162                 return -ENODATA;
1163
1164         r = sd_journal_add_conjunction(j);
1165         if (r < 0)
1166                 return r;
1167
1168         return 0;
1169 }
1170
1171 static int add_priorities(sd_journal *j) {
1172         char match[] = "PRIORITY=0";
1173         int i, r;
1174         assert(j);
1175
1176         if (arg_priorities == 0xFF)
1177                 return 0;
1178
1179         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1180                 if (arg_priorities & (1 << i)) {
1181                         match[sizeof(match)-2] = '0' + i;
1182
1183                         r = sd_journal_add_match(j, match, strlen(match));
1184                         if (r < 0) {
1185                                 log_error("Failed to add match: %s", strerror(-r));
1186                                 return r;
1187                         }
1188                 }
1189
1190         r = sd_journal_add_conjunction(j);
1191         if (r < 0)
1192                 return r;
1193
1194         return 0;
1195 }
1196
1197 static int setup_keys(void) {
1198 #ifdef HAVE_GCRYPT
1199         size_t mpk_size, seed_size, state_size, i;
1200         uint8_t *mpk, *seed, *state;
1201         ssize_t l;
1202         int fd = -1, r, attr = 0;
1203         sd_id128_t machine, boot;
1204         char *p = NULL, *k = NULL;
1205         struct FSSHeader h;
1206         uint64_t n;
1207         struct stat st;
1208
1209         r = stat("/var/log/journal", &st);
1210         if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
1211                 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
1212                 return -errno;
1213         }
1214
1215         if (r < 0 || !S_ISDIR(st.st_mode)) {
1216                 log_error("%s is not a directory, must be using persistent logging for FSS.",
1217                           "/var/log/journal");
1218                 return r < 0 ? -errno : -ENOTDIR;
1219         }
1220
1221         r = sd_id128_get_machine(&machine);
1222         if (r < 0) {
1223                 log_error("Failed to get machine ID: %s", strerror(-r));
1224                 return r;
1225         }
1226
1227         r = sd_id128_get_boot(&boot);
1228         if (r < 0) {
1229                 log_error("Failed to get boot ID: %s", strerror(-r));
1230                 return r;
1231         }
1232
1233         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1234                      SD_ID128_FORMAT_VAL(machine)) < 0)
1235                 return log_oom();
1236
1237         if (access(p, F_OK) >= 0) {
1238                 if (arg_force) {
1239                         r = unlink(p);
1240                         if (r < 0) {
1241                                 log_error("unlink(\"%s\") failed: %m", p);
1242                                 r = -errno;
1243                                 goto finish;
1244                         }
1245                 } else {
1246                         log_error("Sealing key file %s exists already. (--force to recreate)", p);
1247                         r = -EEXIST;
1248                         goto finish;
1249                 }
1250         }
1251
1252         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1253                      SD_ID128_FORMAT_VAL(machine)) < 0) {
1254                 r = log_oom();
1255                 goto finish;
1256         }
1257
1258         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1259         mpk = alloca(mpk_size);
1260
1261         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1262         seed = alloca(seed_size);
1263
1264         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1265         state = alloca(state_size);
1266
1267         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1268         if (fd < 0) {
1269                 log_error("Failed to open /dev/random: %m");
1270                 r = -errno;
1271                 goto finish;
1272         }
1273
1274         log_info("Generating seed...");
1275         l = loop_read(fd, seed, seed_size, true);
1276         if (l < 0 || (size_t) l != seed_size) {
1277                 log_error("Failed to read random seed: %s", strerror(EIO));
1278                 r = -EIO;
1279                 goto finish;
1280         }
1281
1282         log_info("Generating key pair...");
1283         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1284
1285         log_info("Generating sealing key...");
1286         FSPRG_GenState0(state, mpk, seed, seed_size);
1287
1288         assert(arg_interval > 0);
1289
1290         n = now(CLOCK_REALTIME);
1291         n /= arg_interval;
1292
1293         safe_close(fd);
1294         fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1295         if (fd < 0) {
1296                 log_error("Failed to open %s: %m", k);
1297                 r = -errno;
1298                 goto finish;
1299         }
1300
1301         /* Enable secure remove, exclusion from dump, synchronous
1302          * writing and in-place updating */
1303         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
1304                 log_warning("FS_IOC_GETFLAGS failed: %m");
1305
1306         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1307
1308         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1309                 log_warning("FS_IOC_SETFLAGS failed: %m");
1310
1311         zero(h);
1312         memcpy(h.signature, "KSHHRHLP", 8);
1313         h.machine_id = machine;
1314         h.boot_id = boot;
1315         h.header_size = htole64(sizeof(h));
1316         h.start_usec = htole64(n * arg_interval);
1317         h.interval_usec = htole64(arg_interval);
1318         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1319         h.fsprg_state_size = htole64(state_size);
1320
1321         l = loop_write(fd, &h, sizeof(h), false);
1322         if (l < 0 || (size_t) l != sizeof(h)) {
1323                 log_error("Failed to write header: %s", strerror(EIO));
1324                 r = -EIO;
1325                 goto finish;
1326         }
1327
1328         l = loop_write(fd, state, state_size, false);
1329         if (l < 0 || (size_t) l != state_size) {
1330                 log_error("Failed to write state: %s", strerror(EIO));
1331                 r = -EIO;
1332                 goto finish;
1333         }
1334
1335         if (link(k, p) < 0) {
1336                 log_error("Failed to link file: %m");
1337                 r = -errno;
1338                 goto finish;
1339         }
1340
1341         if (on_tty()) {
1342                 fprintf(stderr,
1343                         "\n"
1344                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
1345                         "the following local file. This key file is automatically updated when the\n"
1346                         "sealing key is advanced. It should not be used on multiple hosts.\n"
1347                         "\n"
1348                         "\t%s\n"
1349                         "\n"
1350                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
1351                         "at a safe location and should not be saved locally on disk.\n"
1352                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
1353                 fflush(stderr);
1354         }
1355         for (i = 0; i < seed_size; i++) {
1356                 if (i > 0 && i % 3 == 0)
1357                         putchar('-');
1358                 printf("%02x", ((uint8_t*) seed)[i]);
1359         }
1360
1361         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1362
1363         if (on_tty()) {
1364                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1365
1366                 fprintf(stderr,
1367                         ANSI_HIGHLIGHT_OFF "\n"
1368                         "The sealing key is automatically changed every %s.\n",
1369                         format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1370
1371                 hn = gethostname_malloc();
1372
1373                 if (hn) {
1374                         hostname_cleanup(hn, false);
1375                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1376                 } else
1377                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1378
1379 #ifdef HAVE_QRENCODE
1380                 /* If this is not an UTF-8 system don't print any QR codes */
1381                 if (is_locale_utf8()) {
1382                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1383                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1384                 }
1385 #endif
1386                 free(hn);
1387         }
1388
1389         r = 0;
1390
1391 finish:
1392         safe_close(fd);
1393
1394         if (k) {
1395                 unlink(k);
1396                 free(k);
1397         }
1398
1399         free(p);
1400
1401         return r;
1402 #else
1403         log_error("Forward-secure sealing not available.");
1404         return -ENOTSUP;
1405 #endif
1406 }
1407
1408 static int verify(sd_journal *j) {
1409         int r = 0;
1410         Iterator i;
1411         JournalFile *f;
1412
1413         assert(j);
1414
1415         log_show_color(true);
1416
1417         HASHMAP_FOREACH(f, j->files, i) {
1418                 int k;
1419                 usec_t first, validated, last;
1420
1421 #ifdef HAVE_GCRYPT
1422                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1423                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1424 #endif
1425
1426                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1427                 if (k == -EINVAL) {
1428                         /* If the key was invalid give up right-away. */
1429                         return k;
1430                 } else if (k < 0) {
1431                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1432                         r = k;
1433                 } else {
1434                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1435                         log_info("PASS: %s", f->path);
1436
1437                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1438                                 if (validated > 0) {
1439                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
1440                                                  format_timestamp(a, sizeof(a), first),
1441                                                  format_timestamp(b, sizeof(b), validated),
1442                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1443                                 } else if (last > 0)
1444                                         log_info("=> No sealing yet, %s of entries not sealed.",
1445                                                  format_timespan(c, sizeof(c), last - first, 0));
1446                                 else
1447                                         log_info("=> No sealing yet, no entries in file.");
1448                         }
1449                 }
1450         }
1451
1452         return r;
1453 }
1454
1455 #ifdef HAVE_ACL
1456 static int access_check_var_log_journal(sd_journal *j) {
1457         _cleanup_strv_free_ char **g = NULL;
1458         bool have_access;
1459         int r;
1460
1461         assert(j);
1462
1463         have_access = in_group("systemd-journal") > 0;
1464
1465         if (!have_access) {
1466                 /* Let's enumerate all groups from the default ACL of
1467                  * the directory, which generally should allow access
1468                  * to most journal files too */
1469                 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1470                 if (r < 0)
1471                         return r;
1472         }
1473
1474         if (!have_access) {
1475
1476                 if (strv_isempty(g))
1477                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1478                                    "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1479                                    "      turn off this notice.");
1480                 else {
1481                         _cleanup_free_ char *s = NULL;
1482
1483                         r = strv_extend(&g, "systemd-journal");
1484                         if (r < 0)
1485                                 return log_oom();
1486
1487                         strv_sort(g);
1488                         strv_uniq(g);
1489
1490                         s = strv_join(g, "', '");
1491                         if (!s)
1492                                 return log_oom();
1493
1494                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1495                                    "      Users in the groups '%s' can see all messages.\n"
1496                                    "      Pass -q to turn off this notice.", s);
1497                 }
1498         }
1499
1500         return 0;
1501 }
1502 #endif
1503
1504 static int access_check(sd_journal *j) {
1505         Iterator it;
1506         void *code;
1507         int r = 0;
1508
1509         assert(j);
1510
1511         if (set_isempty(j->errors)) {
1512                 if (hashmap_isempty(j->files))
1513                         log_notice("No journal files were found.");
1514                 return 0;
1515         }
1516
1517         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1518 #ifdef HAVE_ACL
1519                 /* If /var/log/journal doesn't even exist,
1520                  * unprivileged users have no access at all */
1521                 if (access("/var/log/journal", F_OK) < 0 &&
1522                     geteuid() != 0 &&
1523                     in_group("systemd-journal") <= 0) {
1524                         log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1525                                   "enabled. Users in the 'systemd-journal' group may always access messages.");
1526                         return -EACCES;
1527                 }
1528
1529                 /* If /var/log/journal exists, try to pring a nice
1530                    notice if the user lacks access to it */
1531                 if (!arg_quiet && geteuid() != 0) {
1532                         r = access_check_var_log_journal(j);
1533                         if (r < 0)
1534                                 return r;
1535                 }
1536 #else
1537                 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1538                         log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1539                                   "group may access messages.");
1540                         return -EACCES;
1541                 }
1542 #endif
1543
1544                 if (hashmap_isempty(j->files)) {
1545                         log_error("No journal files were opened due to insufficient permissions.");
1546                         r = -EACCES;
1547                 }
1548         }
1549
1550         SET_FOREACH(code, j->errors, it) {
1551                 int err;
1552
1553                 err = -PTR_TO_INT(code);
1554                 assert(err > 0);
1555
1556                 if (err != EACCES)
1557                         log_warning("Error was encountered while opening journal files: %s",
1558                                     strerror(err));
1559         }
1560
1561         return r;
1562 }
1563
1564 int main(int argc, char *argv[]) {
1565         int r;
1566         _cleanup_journal_close_ sd_journal *j = NULL;
1567         bool need_seek = false;
1568         sd_id128_t previous_boot_id;
1569         bool previous_boot_id_valid = false, first_line = true;
1570         int n_shown = 0;
1571         bool ellipsized = false;
1572
1573         setlocale(LC_ALL, "");
1574         log_parse_environment();
1575         log_open();
1576
1577         r = parse_argv(argc, argv);
1578         if (r <= 0)
1579                 goto finish;
1580
1581         signal(SIGWINCH, columns_lines_cache_reset);
1582
1583         if (arg_action == ACTION_NEW_ID128) {
1584                 r = generate_new_id128();
1585                 goto finish;
1586         }
1587
1588         if (arg_action == ACTION_SETUP_KEYS) {
1589                 r = setup_keys();
1590                 goto finish;
1591         }
1592
1593         if (arg_action == ACTION_UPDATE_CATALOG ||
1594             arg_action == ACTION_LIST_CATALOG ||
1595             arg_action == ACTION_DUMP_CATALOG) {
1596
1597                 const char* database = CATALOG_DATABASE;
1598                 _cleanup_free_ char *copy = NULL;
1599                 if (arg_root) {
1600                         copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1601                         if (!copy) {
1602                                 r = log_oom();
1603                                 goto finish;
1604                         }
1605                         path_kill_slashes(copy);
1606                         database = copy;
1607                 }
1608
1609                 if (arg_action == ACTION_UPDATE_CATALOG) {
1610                         r = catalog_update(database, arg_root, catalog_file_dirs);
1611                         if (r < 0)
1612                                 log_error("Failed to list catalog: %s", strerror(-r));
1613                 } else {
1614                         bool oneline = arg_action == ACTION_LIST_CATALOG;
1615
1616                         if (optind < argc)
1617                                 r = catalog_list_items(stdout, database,
1618                                                        oneline, argv + optind);
1619                         else
1620                                 r = catalog_list(stdout, database, oneline);
1621                         if (r < 0)
1622                                 log_error("Failed to list catalog: %s", strerror(-r));
1623                 }
1624
1625                 goto finish;
1626         }
1627
1628         if (arg_directory)
1629                 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1630         else if (arg_file)
1631                 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1632         else if (arg_machine)
1633                 r = sd_journal_open_container(&j, arg_machine, 0);
1634         else
1635                 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1636         if (r < 0) {
1637                 log_error("Failed to open %s: %s",
1638                           arg_directory ? arg_directory : arg_file ? "files" : "journal",
1639                           strerror(-r));
1640                 return EXIT_FAILURE;
1641         }
1642
1643         r = access_check(j);
1644         if (r < 0)
1645                 return EXIT_FAILURE;
1646
1647         if (arg_action == ACTION_VERIFY) {
1648                 r = verify(j);
1649                 goto finish;
1650         }
1651
1652         if (arg_action == ACTION_PRINT_HEADER) {
1653                 journal_print_header(j);
1654                 return EXIT_SUCCESS;
1655         }
1656
1657         if (arg_action == ACTION_DISK_USAGE) {
1658                 uint64_t bytes = 0;
1659                 char sbytes[FORMAT_BYTES_MAX];
1660
1661                 r = sd_journal_get_usage(j, &bytes);
1662                 if (r < 0)
1663                         return EXIT_FAILURE;
1664
1665                 printf("Journals take up %s on disk.\n",
1666                        format_bytes(sbytes, sizeof(sbytes), bytes));
1667                 return EXIT_SUCCESS;
1668         }
1669
1670         if (arg_action == ACTION_LIST_BOOTS) {
1671                 r = list_boots(j);
1672                 goto finish;
1673         }
1674
1675         /* add_boot() must be called first!
1676          * It may need to seek the journal to find parent boot IDs. */
1677         r = add_boot(j);
1678         if (r < 0)
1679                 return EXIT_FAILURE;
1680
1681         r = add_dmesg(j);
1682         if (r < 0)
1683                 return EXIT_FAILURE;
1684
1685         r = add_units(j);
1686         strv_free(arg_system_units);
1687         strv_free(arg_user_units);
1688
1689         if (r < 0) {
1690                 log_error("Failed to add filter for units: %s", strerror(-r));
1691                 return EXIT_FAILURE;
1692         }
1693
1694         r = add_priorities(j);
1695         if (r < 0) {
1696                 log_error("Failed to add filter for priorities: %s", strerror(-r));
1697                 return EXIT_FAILURE;
1698         }
1699
1700         r = add_matches(j, argv + optind);
1701         if (r < 0) {
1702                 log_error("Failed to add filters: %s", strerror(-r));
1703                 return EXIT_FAILURE;
1704         }
1705
1706         if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1707                 _cleanup_free_ char *filter;
1708
1709                 filter = journal_make_match_string(j);
1710                 log_debug("Journal filter: %s", filter);
1711         }
1712
1713         if (arg_field) {
1714                 const void *data;
1715                 size_t size;
1716
1717                 r = sd_journal_set_data_threshold(j, 0);
1718                 if (r < 0) {
1719                         log_error("Failed to unset data size threshold");
1720                         return EXIT_FAILURE;
1721                 }
1722
1723                 r = sd_journal_query_unique(j, arg_field);
1724                 if (r < 0) {
1725                         log_error("Failed to query unique data objects: %s", strerror(-r));
1726                         return EXIT_FAILURE;
1727                 }
1728
1729                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1730                         const void *eq;
1731
1732                         if (arg_lines >= 0 && n_shown >= arg_lines)
1733                                 break;
1734
1735                         eq = memchr(data, '=', size);
1736                         if (eq)
1737                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1738                         else
1739                                 printf("%.*s\n", (int) size, (const char*) data);
1740
1741                         n_shown ++;
1742                 }
1743
1744                 return EXIT_SUCCESS;
1745         }
1746
1747         /* Opening the fd now means the first sd_journal_wait() will actually wait */
1748         if (arg_follow) {
1749                 r = sd_journal_get_fd(j);
1750                 if (r < 0)
1751                         return EXIT_FAILURE;
1752         }
1753
1754         if (arg_cursor || arg_after_cursor) {
1755                 r = sd_journal_seek_cursor(j, arg_cursor ? arg_cursor : arg_after_cursor);
1756                 if (r < 0) {
1757                         log_error("Failed to seek to cursor: %s", strerror(-r));
1758                         return EXIT_FAILURE;
1759                 }
1760                 if (!arg_reverse)
1761                         r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1762                 else
1763                         r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1764
1765                 if (arg_after_cursor && r < 2 && !arg_follow)
1766                         /* We couldn't find the next entry after the cursor. */
1767                         arg_lines = 0;
1768
1769         } else if (arg_since_set && !arg_reverse) {
1770                 r = sd_journal_seek_realtime_usec(j, arg_since);
1771                 if (r < 0) {
1772                         log_error("Failed to seek to date: %s", strerror(-r));
1773                         return EXIT_FAILURE;
1774                 }
1775                 r = sd_journal_next(j);
1776
1777         } else if (arg_until_set && arg_reverse) {
1778                 r = sd_journal_seek_realtime_usec(j, arg_until);
1779                 if (r < 0) {
1780                         log_error("Failed to seek to date: %s", strerror(-r));
1781                         return EXIT_FAILURE;
1782                 }
1783                 r = sd_journal_previous(j);
1784
1785         } else if (arg_lines >= 0) {
1786                 r = sd_journal_seek_tail(j);
1787                 if (r < 0) {
1788                         log_error("Failed to seek to tail: %s", strerror(-r));
1789                         return EXIT_FAILURE;
1790                 }
1791
1792                 r = sd_journal_previous_skip(j, arg_lines);
1793
1794         } else if (arg_reverse) {
1795                 r = sd_journal_seek_tail(j);
1796                 if (r < 0) {
1797                         log_error("Failed to seek to tail: %s", strerror(-r));
1798                         return EXIT_FAILURE;
1799                 }
1800
1801                 r = sd_journal_previous(j);
1802
1803         } else {
1804                 r = sd_journal_seek_head(j);
1805                 if (r < 0) {
1806                         log_error("Failed to seek to head: %s", strerror(-r));
1807                         return EXIT_FAILURE;
1808                 }
1809
1810                 r = sd_journal_next(j);
1811         }
1812
1813         if (r < 0) {
1814                 log_error("Failed to iterate through journal: %s", strerror(-r));
1815                 return EXIT_FAILURE;
1816         }
1817
1818         if (!arg_follow)
1819                 pager_open_if_enabled();
1820
1821         if (!arg_quiet) {
1822                 usec_t start, end;
1823                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1824
1825                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1826                 if (r < 0) {
1827                         log_error("Failed to get cutoff: %s", strerror(-r));
1828                         goto finish;
1829                 }
1830
1831                 if (r > 0) {
1832                         if (arg_follow)
1833                                 printf("-- Logs begin at %s. --\n",
1834                                        format_timestamp(start_buf, sizeof(start_buf), start));
1835                         else
1836                                 printf("-- Logs begin at %s, end at %s. --\n",
1837                                        format_timestamp(start_buf, sizeof(start_buf), start),
1838                                        format_timestamp(end_buf, sizeof(end_buf), end));
1839                 }
1840         }
1841
1842         for (;;) {
1843                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1844                         int flags;
1845
1846                         if (need_seek) {
1847                                 if (!arg_reverse)
1848                                         r = sd_journal_next(j);
1849                                 else
1850                                         r = sd_journal_previous(j);
1851                                 if (r < 0) {
1852                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1853                                         goto finish;
1854                                 }
1855                                 if (r == 0)
1856                                         break;
1857                         }
1858
1859                         if (arg_until_set && !arg_reverse) {
1860                                 usec_t usec;
1861
1862                                 r = sd_journal_get_realtime_usec(j, &usec);
1863                                 if (r < 0) {
1864                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1865                                         goto finish;
1866                                 }
1867                                 if (usec > arg_until)
1868                                         goto finish;
1869                         }
1870
1871                         if (arg_since_set && arg_reverse) {
1872                                 usec_t usec;
1873
1874                                 r = sd_journal_get_realtime_usec(j, &usec);
1875                                 if (r < 0) {
1876                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1877                                         goto finish;
1878                                 }
1879                                 if (usec < arg_since)
1880                                         goto finish;
1881                         }
1882
1883                         if (!arg_merge) {
1884                                 sd_id128_t boot_id;
1885
1886                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1887                                 if (r >= 0) {
1888                                         if (previous_boot_id_valid &&
1889                                             !sd_id128_equal(boot_id, previous_boot_id))
1890                                                 printf("%s-- Reboot --%s\n",
1891                                                        ansi_highlight(), ansi_highlight_off());
1892
1893                                         previous_boot_id = boot_id;
1894                                         previous_boot_id_valid = true;
1895                                 }
1896                         }
1897
1898                         flags =
1899                                 arg_all * OUTPUT_SHOW_ALL |
1900                                 arg_full * OUTPUT_FULL_WIDTH |
1901                                 on_tty() * OUTPUT_COLOR |
1902                                 arg_catalog * OUTPUT_CATALOG;
1903
1904                         r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
1905                         need_seek = true;
1906                         if (r == -EADDRNOTAVAIL)
1907                                 break;
1908                         else if (r < 0 || ferror(stdout))
1909                                 goto finish;
1910
1911                         n_shown++;
1912                 }
1913
1914                 if (!arg_follow) {
1915                         if (arg_show_cursor) {
1916                                 _cleanup_free_ char *cursor = NULL;
1917
1918                                 r = sd_journal_get_cursor(j, &cursor);
1919                                 if (r < 0 && r != -EADDRNOTAVAIL)
1920                                         log_error("Failed to get cursor: %s", strerror(-r));
1921                                 else if (r >= 0)
1922                                         printf("-- cursor: %s\n", cursor);
1923                         }
1924
1925                         break;
1926                 }
1927
1928                 r = sd_journal_wait(j, (uint64_t) -1);
1929                 if (r < 0) {
1930                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1931                         goto finish;
1932                 }
1933
1934                 first_line = false;
1935         }
1936
1937 finish:
1938         pager_close();
1939
1940         strv_free(arg_file);
1941
1942         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1943 }