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