chiark / gitweb /
002ff7cda08d5ad98c52b383cd7122de0672e9f2
[elogind.git] / src / journal / journalctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <locale.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <stddef.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <time.h>
31 #include <getopt.h>
32 #include <signal.h>
33 #include <sys/stat.h>
34 #include <sys/ioctl.h>
35 #include <linux/fs.h>
36
37 #ifdef HAVE_ACL
38 #include <sys/acl.h>
39 #include "acl-util.h"
40 #endif
41
42 #include <systemd/sd-journal.h>
43
44 #include "log.h"
45 #include "logs-show.h"
46 #include "util.h"
47 #include "path-util.h"
48 #include "build.h"
49 #include "pager.h"
50 #include "logs-show.h"
51 #include "strv.h"
52 #include "journal-internal.h"
53 #include "journal-def.h"
54 #include "journal-verify.h"
55 #include "journal-authenticate.h"
56 #include "journal-qrcode.h"
57 #include "fsprg.h"
58 #include "unit-name.h"
59 #include "catalog.h"
60
61 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
62
63 static OutputMode arg_output = OUTPUT_SHORT;
64 static bool arg_pager_end = false;
65 static bool arg_follow = false;
66 static bool arg_full = false;
67 static bool arg_all = false;
68 static bool arg_no_pager = false;
69 static int arg_lines = -1;
70 static bool arg_no_tail = false;
71 static bool arg_quiet = false;
72 static bool arg_merge = false;
73 static bool arg_this_boot = false;
74 static const char *arg_cursor = NULL;
75 static const char *arg_directory = NULL;
76 static int arg_priorities = 0xFF;
77 static const char *arg_verify_key = NULL;
78 #ifdef HAVE_GCRYPT
79 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
80 #endif
81 static usec_t arg_since, arg_until;
82 static bool arg_since_set = false, arg_until_set = false;
83 static const char *arg_unit = NULL;
84 static bool arg_unit_system;
85 static const char *arg_field = NULL;
86 static bool arg_catalog = false;
87 static bool arg_reverse = false;
88 static const char *arg_root = NULL;
89
90 static enum {
91         ACTION_SHOW,
92         ACTION_NEW_ID128,
93         ACTION_PRINT_HEADER,
94         ACTION_SETUP_KEYS,
95         ACTION_VERIFY,
96         ACTION_DISK_USAGE,
97         ACTION_LIST_CATALOG,
98         ACTION_DUMP_CATALOG,
99         ACTION_UPDATE_CATALOG
100 } arg_action = ACTION_SHOW;
101
102 static int help(void) {
103
104         printf("%s [OPTIONS...] [MATCHES...]\n\n"
105                "Query the journal.\n\n"
106                "Flags:\n"
107                "     --since=DATE        Start showing entries newer or of the specified date\n"
108                "     --until=DATE        Stop showing entries older or of the specified date\n"
109                "  -c --cursor=CURSOR     Start showing entries from specified cursor\n"
110                "  -b --this-boot         Show data only from current boot\n"
111                "  -u --unit=UNIT         Show data only from the specified unit\n"
112                "     --user-unit=UNIT    Show data only from the specified user session unit\n"
113                "  -p --priority=RANGE    Show only messages within the specified priority range\n"
114                "  -e --pager-end         Immediately jump to end of the journal in the pager\n"
115                "  -f --follow            Follow journal\n"
116                "  -n --lines[=INTEGER]   Number of journal entries to show\n"
117                "     --no-tail           Show all lines, even in follow mode\n"
118                "  -r --reverse           Show the newest entries first\n"
119                "  -o --output=STRING     Change journal output mode (short, short-monotonic,\n"
120                "                         verbose, export, json, json-pretty, json-sse, cat)\n"
121                "  -x --catalog           Add message explanations where available\n"
122                "     --full              Do not ellipsize fields\n"
123                "  -a --all               Show all fields, including long and unprintable\n"
124                "  -q --quiet             Don't show privilege warning\n"
125                "     --no-pager          Do not pipe output into a pager\n"
126                "  -m --merge             Show entries from all available journals\n"
127                "  -D --directory=PATH    Show journal files from directory\n"
128                "     --root=ROOT         Operate on catalog files underneath the root ROOT\n"
129 #ifdef HAVE_GCRYPT
130                "     --interval=TIME     Time interval for changing the FSS sealing key\n"
131                "     --verify-key=KEY    Specify FSS verification key\n"
132 #endif
133                "\nCommands:\n"
134                "  -h --help              Show this help\n"
135                "     --version           Show package version\n"
136                "     --new-id128         Generate a new 128 Bit ID\n"
137                "     --header            Show journal header information\n"
138                "     --disk-usage        Show total disk usage\n"
139                "  -F --field=FIELD       List all values a certain field takes\n"
140                "     --list-catalog      Show message IDs of all entries in the message catalog\n"
141                "     --dump-catalog      Show entries in the message catalog\n"
142                "     --update-catalog    Update the message catalog database\n"
143 #ifdef HAVE_GCRYPT
144                "     --setup-keys        Generate new FSS key pair\n"
145                "     --verify            Verify journal file consistency\n"
146 #endif
147                , program_invocation_short_name);
148
149         return 0;
150 }
151
152 static int parse_argv(int argc, char *argv[]) {
153
154         enum {
155                 ARG_VERSION = 0x100,
156                 ARG_NO_PAGER,
157                 ARG_NO_TAIL,
158                 ARG_NEW_ID128,
159                 ARG_ROOT,
160                 ARG_HEADER,
161                 ARG_FULL,
162                 ARG_SETUP_KEYS,
163                 ARG_INTERVAL,
164                 ARG_VERIFY,
165                 ARG_VERIFY_KEY,
166                 ARG_DISK_USAGE,
167                 ARG_SINCE,
168                 ARG_UNTIL,
169                 ARG_USER_UNIT,
170                 ARG_LIST_CATALOG,
171                 ARG_DUMP_CATALOG,
172                 ARG_UPDATE_CATALOG
173         };
174
175         static const struct option options[] = {
176                 { "help",         no_argument,       NULL, 'h'              },
177                 { "version" ,     no_argument,       NULL, ARG_VERSION      },
178                 { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
179                 { "pager-end",    no_argument,       NULL, 'e'              },
180                 { "follow",       no_argument,       NULL, 'f'              },
181                 { "output",       required_argument, NULL, 'o'              },
182                 { "all",          no_argument,       NULL, 'a'              },
183                 { "full",         no_argument,       NULL, ARG_FULL         },
184                 { "lines",        optional_argument, NULL, 'n'              },
185                 { "no-tail",      no_argument,       NULL, ARG_NO_TAIL      },
186                 { "new-id128",    no_argument,       NULL, ARG_NEW_ID128    },
187                 { "quiet",        no_argument,       NULL, 'q'              },
188                 { "merge",        no_argument,       NULL, 'm'              },
189                 { "this-boot",    no_argument,       NULL, 'b'              },
190                 { "directory",    required_argument, NULL, 'D'              },
191                 { "root",         required_argument, NULL, ARG_ROOT         },
192                 { "header",       no_argument,       NULL, ARG_HEADER       },
193                 { "priority",     required_argument, NULL, 'p'              },
194                 { "setup-keys",   no_argument,       NULL, ARG_SETUP_KEYS   },
195                 { "interval",     required_argument, NULL, ARG_INTERVAL     },
196                 { "verify",       no_argument,       NULL, ARG_VERIFY       },
197                 { "verify-key",   required_argument, NULL, ARG_VERIFY_KEY   },
198                 { "disk-usage",   no_argument,       NULL, ARG_DISK_USAGE   },
199                 { "cursor",       required_argument, NULL, 'c'              },
200                 { "since",        required_argument, NULL, ARG_SINCE        },
201                 { "until",        required_argument, NULL, ARG_UNTIL        },
202                 { "unit",         required_argument, NULL, 'u'              },
203                 { "user-unit",    required_argument, NULL, ARG_USER_UNIT    },
204                 { "field",        required_argument, NULL, 'F'              },
205                 { "catalog",      no_argument,       NULL, 'x'              },
206                 { "list-catalog", no_argument,       NULL, ARG_LIST_CATALOG },
207                 { "dump-catalog", no_argument,       NULL, ARG_DUMP_CATALOG },
208                 { "update-catalog",no_argument,      NULL, ARG_UPDATE_CATALOG },
209                 { "reverse",      no_argument,       NULL, 'r'              },
210                 { NULL,           0,                 NULL, 0                }
211         };
212
213         int c, r;
214
215         assert(argc >= 0);
216         assert(argv);
217
218         while ((c = getopt_long(argc, argv, "hefo:an::qmbD:p:c:u:F:xr", options, NULL)) >= 0) {
219
220                 switch (c) {
221
222                 case 'h':
223                         help();
224                         return 0;
225
226                 case ARG_VERSION:
227                         puts(PACKAGE_STRING);
228                         puts(SYSTEMD_FEATURES);
229                         return 0;
230
231                 case ARG_NO_PAGER:
232                         arg_no_pager = true;
233                         break;
234
235                 case 'e':
236                         arg_pager_end = true;
237
238                         if (arg_lines < 0)
239                                 arg_lines = 1000;
240
241                         break;
242
243                 case 'f':
244                         arg_follow = true;
245                         break;
246
247                 case 'o':
248                         arg_output = output_mode_from_string(optarg);
249                         if (arg_output < 0) {
250                                 log_error("Unknown output format '%s'.", optarg);
251                                 return -EINVAL;
252                         }
253
254                         if (arg_output == OUTPUT_EXPORT ||
255                             arg_output == OUTPUT_JSON ||
256                             arg_output == OUTPUT_JSON_PRETTY ||
257                             arg_output == OUTPUT_JSON_SSE ||
258                             arg_output == OUTPUT_CAT)
259                                 arg_quiet = true;
260
261                         break;
262
263                 case ARG_FULL:
264                         arg_full = true;
265                         break;
266
267                 case 'a':
268                         arg_all = true;
269                         break;
270
271                 case 'n':
272                         if (optarg) {
273                                 r = safe_atoi(optarg, &arg_lines);
274                                 if (r < 0 || arg_lines < 0) {
275                                         log_error("Failed to parse lines '%s'", optarg);
276                                         return -EINVAL;
277                                 }
278                         } else {
279                                 int n;
280
281                                 /* Hmm, no argument? Maybe the next
282                                  * word on the command line is
283                                  * supposed to be the argument? Let's
284                                  * see if there is one, and is
285                                  * parsable as a positive
286                                  * integer... */
287
288                                 if (optind < argc &&
289                                     safe_atoi(argv[optind], &n) >= 0 &&
290                                     n >= 0) {
291
292                                         arg_lines = n;
293                                         optind++;
294                                 } else
295                                         arg_lines = 10;
296                         }
297
298                         break;
299
300                 case ARG_NO_TAIL:
301                         arg_no_tail = true;
302                         break;
303
304                 case ARG_NEW_ID128:
305                         arg_action = ACTION_NEW_ID128;
306                         break;
307
308                 case 'q':
309                         arg_quiet = true;
310                         break;
311
312                 case 'm':
313                         arg_merge = true;
314                         break;
315
316                 case 'b':
317                         arg_this_boot = true;
318                         break;
319
320                 case 'D':
321                         arg_directory = optarg;
322                         break;
323
324                 case ARG_ROOT:
325                         arg_root = optarg;
326                         break;
327
328                 case 'c':
329                         arg_cursor = optarg;
330                         break;
331
332                 case ARG_HEADER:
333                         arg_action = ACTION_PRINT_HEADER;
334                         break;
335
336                 case ARG_VERIFY:
337                         arg_action = ACTION_VERIFY;
338                         break;
339
340                 case ARG_DISK_USAGE:
341                         arg_action = ACTION_DISK_USAGE;
342                         break;
343
344 #ifdef HAVE_GCRYPT
345                 case ARG_SETUP_KEYS:
346                         arg_action = ACTION_SETUP_KEYS;
347                         break;
348
349
350                 case ARG_VERIFY_KEY:
351                         arg_action = ACTION_VERIFY;
352                         arg_verify_key = optarg;
353                         arg_merge = false;
354                         break;
355
356                 case ARG_INTERVAL:
357                         r = parse_sec(optarg, &arg_interval);
358                         if (r < 0 || arg_interval <= 0) {
359                                 log_error("Failed to parse sealing key change interval: %s", optarg);
360                                 return -EINVAL;
361                         }
362                         break;
363 #else
364                 case ARG_SETUP_KEYS:
365                 case ARG_VERIFY_KEY:
366                 case ARG_INTERVAL:
367                         log_error("Forward-secure sealing not available.");
368                         return -ENOTSUP;
369 #endif
370
371                 case 'p': {
372                         const char *dots;
373
374                         dots = strstr(optarg, "..");
375                         if (dots) {
376                                 char *a;
377                                 int from, to, i;
378
379                                 /* a range */
380                                 a = strndup(optarg, dots - optarg);
381                                 if (!a)
382                                         return log_oom();
383
384                                 from = log_level_from_string(a);
385                                 to = log_level_from_string(dots + 2);
386                                 free(a);
387
388                                 if (from < 0 || to < 0) {
389                                         log_error("Failed to parse log level range %s", optarg);
390                                         return -EINVAL;
391                                 }
392
393                                 arg_priorities = 0;
394
395                                 if (from < to) {
396                                         for (i = from; i <= to; i++)
397                                                 arg_priorities |= 1 << i;
398                                 } else {
399                                         for (i = to; i <= from; i++)
400                                                 arg_priorities |= 1 << i;
401                                 }
402
403                         } else {
404                                 int p, i;
405
406                                 p = log_level_from_string(optarg);
407                                 if (p < 0) {
408                                         log_error("Unknown log level %s", optarg);
409                                         return -EINVAL;
410                                 }
411
412                                 arg_priorities = 0;
413
414                                 for (i = 0; i <= p; i++)
415                                         arg_priorities |= 1 << i;
416                         }
417
418                         break;
419                 }
420
421                 case ARG_SINCE:
422                         r = parse_timestamp(optarg, &arg_since);
423                         if (r < 0) {
424                                 log_error("Failed to parse timestamp: %s", optarg);
425                                 return -EINVAL;
426                         }
427                         arg_since_set = true;
428                         break;
429
430                 case ARG_UNTIL:
431                         r = parse_timestamp(optarg, &arg_until);
432                         if (r < 0) {
433                                 log_error("Failed to parse timestamp: %s", optarg);
434                                 return -EINVAL;
435                         }
436                         arg_until_set = true;
437                         break;
438
439                 case 'u':
440                         arg_unit = optarg;
441                         arg_unit_system = true;
442                         break;
443
444                 case ARG_USER_UNIT:
445                         arg_unit = optarg;
446                         arg_unit_system = false;
447                         break;
448
449                 case '?':
450                         return -EINVAL;
451
452                 case 'F':
453                         arg_field = optarg;
454                         break;
455
456                 case 'x':
457                         arg_catalog = true;
458                         break;
459
460                 case ARG_LIST_CATALOG:
461                         arg_action = ACTION_LIST_CATALOG;
462                         break;
463
464                 case ARG_DUMP_CATALOG:
465                         arg_action = ACTION_DUMP_CATALOG;
466                         break;
467
468                 case ARG_UPDATE_CATALOG:
469                         arg_action = ACTION_UPDATE_CATALOG;
470                         break;
471
472                 case 'r':
473                         arg_reverse = true;
474                         break;
475
476                 default:
477                         log_error("Unknown option code %c", c);
478                         return -EINVAL;
479                 }
480         }
481
482         if (arg_follow && !arg_no_tail && arg_lines < 0)
483                 arg_lines = 10;
484
485         if (arg_since_set && arg_until_set && arg_since > arg_until) {
486                 log_error("--since= must be before --until=.");
487                 return -EINVAL;
488         }
489
490         if (arg_cursor && arg_since_set) {
491                 log_error("Please specify either --since= or --cursor=, not both.");
492                 return -EINVAL;
493         }
494
495         if (arg_follow && arg_reverse) {
496                 log_error("Please specify either --reverse= or --follow=, not both.");
497                 return -EINVAL;
498         }
499
500         return 1;
501 }
502
503 static int generate_new_id128(void) {
504         sd_id128_t id;
505         int r;
506         unsigned i;
507
508         r = sd_id128_randomize(&id);
509         if (r < 0) {
510                 log_error("Failed to generate ID: %s", strerror(-r));
511                 return r;
512         }
513
514         printf("As string:\n"
515                SD_ID128_FORMAT_STR "\n\n"
516                "As UUID:\n"
517                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
518                "As macro:\n"
519                "#define MESSAGE_XYZ SD_ID128_MAKE(",
520                SD_ID128_FORMAT_VAL(id),
521                SD_ID128_FORMAT_VAL(id));
522         for (i = 0; i < 16; i++)
523                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
524         fputs(")\n\n", stdout);
525
526         printf("As Python constant:\n"
527                ">>> import uuid\n"
528                ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
529                SD_ID128_FORMAT_VAL(id));
530
531         return 0;
532 }
533
534 static int add_matches(sd_journal *j, char **args) {
535         char **i;
536
537         assert(j);
538
539         STRV_FOREACH(i, args) {
540                 int r;
541
542                 if (streq(*i, "+"))
543                         r = sd_journal_add_disjunction(j);
544                 else if (path_is_absolute(*i)) {
545                         char _cleanup_free_ *p, *t = NULL;
546                         const char *path;
547                         struct stat st;
548
549                         p = canonicalize_file_name(*i);
550                         path = p ? p : *i;
551
552                         if (stat(path, &st) < 0)  {
553                                 log_error("Couldn't stat file: %m");
554                                 return -errno;
555                         }
556
557                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
558                                 t = strappend("_EXE=", path);
559                         else if (S_ISCHR(st.st_mode))
560                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
561                         else if (S_ISBLK(st.st_mode))
562                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
563                         else {
564                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
565                                 return -EINVAL;
566                         }
567
568                         if (!t)
569                                 return log_oom();
570
571                         r = sd_journal_add_match(j, t, 0);
572                 } else
573                         r = sd_journal_add_match(j, *i, 0);
574
575                 if (r < 0) {
576                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
577                         return r;
578                 }
579         }
580
581         return 0;
582 }
583
584 static int add_this_boot(sd_journal *j) {
585         char match[9+32+1] = "_BOOT_ID=";
586         sd_id128_t boot_id;
587         int r;
588
589         assert(j);
590
591         if (!arg_this_boot)
592                 return 0;
593
594         r = sd_id128_get_boot(&boot_id);
595         if (r < 0) {
596                 log_error("Failed to get boot id: %s", strerror(-r));
597                 return r;
598         }
599
600         sd_id128_to_string(boot_id, match + 9);
601         r = sd_journal_add_match(j, match, strlen(match));
602         if (r < 0) {
603                 log_error("Failed to add match: %s", strerror(-r));
604                 return r;
605         }
606
607         return 0;
608 }
609
610 static int add_unit(sd_journal *j) {
611         _cleanup_free_ char *u = NULL;
612         int r;
613
614         assert(j);
615
616         if (isempty(arg_unit))
617                 return 0;
618
619         u = unit_name_mangle(arg_unit);
620         if (!u)
621                 return log_oom();
622
623         if (arg_unit_system)
624                 r = add_matches_for_unit(j, u);
625         else
626                 r = add_matches_for_user_unit(j, u, getuid());
627         if (r < 0)
628                 return r;
629
630         return 0;
631 }
632
633 static int add_priorities(sd_journal *j) {
634         char match[] = "PRIORITY=0";
635         int i, r;
636
637         assert(j);
638
639         if (arg_priorities == 0xFF)
640                 return 0;
641
642         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
643                 if (arg_priorities & (1 << i)) {
644                         match[sizeof(match)-2] = '0' + i;
645
646                         r = sd_journal_add_match(j, match, strlen(match));
647                         if (r < 0) {
648                                 log_error("Failed to add match: %s", strerror(-r));
649                                 return r;
650                         }
651                 }
652
653         return 0;
654 }
655
656 static int setup_keys(void) {
657 #ifdef HAVE_GCRYPT
658         size_t mpk_size, seed_size, state_size, i;
659         uint8_t *mpk, *seed, *state;
660         ssize_t l;
661         int fd = -1, r, attr = 0;
662         sd_id128_t machine, boot;
663         char *p = NULL, *k = NULL;
664         struct FSSHeader h;
665         uint64_t n;
666
667         r = sd_id128_get_machine(&machine);
668         if (r < 0) {
669                 log_error("Failed to get machine ID: %s", strerror(-r));
670                 return r;
671         }
672
673         r = sd_id128_get_boot(&boot);
674         if (r < 0) {
675                 log_error("Failed to get boot ID: %s", strerror(-r));
676                 return r;
677         }
678
679         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
680                      SD_ID128_FORMAT_VAL(machine)) < 0)
681                 return log_oom();
682
683         if (access(p, F_OK) >= 0) {
684                 log_error("Sealing key file %s exists already.", p);
685                 r = -EEXIST;
686                 goto finish;
687         }
688
689         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
690                      SD_ID128_FORMAT_VAL(machine)) < 0) {
691                 r = log_oom();
692                 goto finish;
693         }
694
695         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
696         mpk = alloca(mpk_size);
697
698         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
699         seed = alloca(seed_size);
700
701         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
702         state = alloca(state_size);
703
704         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
705         if (fd < 0) {
706                 log_error("Failed to open /dev/random: %m");
707                 r = -errno;
708                 goto finish;
709         }
710
711         log_info("Generating seed...");
712         l = loop_read(fd, seed, seed_size, true);
713         if (l < 0 || (size_t) l != seed_size) {
714                 log_error("Failed to read random seed: %s", strerror(EIO));
715                 r = -EIO;
716                 goto finish;
717         }
718
719         log_info("Generating key pair...");
720         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
721
722         log_info("Generating sealing key...");
723         FSPRG_GenState0(state, mpk, seed, seed_size);
724
725         assert(arg_interval > 0);
726
727         n = now(CLOCK_REALTIME);
728         n /= arg_interval;
729
730         close_nointr_nofail(fd);
731         fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
732         if (fd < 0) {
733                 log_error("Failed to open %s: %m", k);
734                 r = -errno;
735                 goto finish;
736         }
737
738         /* Enable secure remove, exclusion from dump, synchronous
739          * writing and in-place updating */
740         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
741                 log_warning("FS_IOC_GETFLAGS failed: %m");
742
743         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
744
745         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
746                 log_warning("FS_IOC_SETFLAGS failed: %m");
747
748         zero(h);
749         memcpy(h.signature, "KSHHRHLP", 8);
750         h.machine_id = machine;
751         h.boot_id = boot;
752         h.header_size = htole64(sizeof(h));
753         h.start_usec = htole64(n * arg_interval);
754         h.interval_usec = htole64(arg_interval);
755         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
756         h.fsprg_state_size = htole64(state_size);
757
758         l = loop_write(fd, &h, sizeof(h), false);
759         if (l < 0 || (size_t) l != sizeof(h)) {
760                 log_error("Failed to write header: %s", strerror(EIO));
761                 r = -EIO;
762                 goto finish;
763         }
764
765         l = loop_write(fd, state, state_size, false);
766         if (l < 0 || (size_t) l != state_size) {
767                 log_error("Failed to write state: %s", strerror(EIO));
768                 r = -EIO;
769                 goto finish;
770         }
771
772         if (link(k, p) < 0) {
773                 log_error("Failed to link file: %m");
774                 r = -errno;
775                 goto finish;
776         }
777
778         if (on_tty()) {
779                 fprintf(stderr,
780                         "\n"
781                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
782                         "the following local file. This key file is automatically updated when the\n"
783                         "sealing key is advanced. It should not be used on multiple hosts.\n"
784                         "\n"
785                         "\t%s\n"
786                         "\n"
787                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
788                         "at a safe location and should not be saved locally on disk.\n"
789                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
790                 fflush(stderr);
791         }
792         for (i = 0; i < seed_size; i++) {
793                 if (i > 0 && i % 3 == 0)
794                         putchar('-');
795                 printf("%02x", ((uint8_t*) seed)[i]);
796         }
797
798         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
799
800         if (on_tty()) {
801                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
802
803                 fprintf(stderr,
804                         ANSI_HIGHLIGHT_OFF "\n"
805                         "The sealing key is automatically changed every %s.\n",
806                         format_timespan(tsb, sizeof(tsb), arg_interval, 0));
807
808                 hn = gethostname_malloc();
809
810                 if (hn) {
811                         hostname_cleanup(hn);
812                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
813                 } else
814                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
815
816 #ifdef HAVE_QRENCODE
817                 /* If this is not an UTF-8 system don't print any QR codes */
818                 if (is_locale_utf8()) {
819                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
820                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
821                 }
822 #endif
823                 free(hn);
824         }
825
826         r = 0;
827
828 finish:
829         if (fd >= 0)
830                 close_nointr_nofail(fd);
831
832         if (k) {
833                 unlink(k);
834                 free(k);
835         }
836
837         free(p);
838
839         return r;
840 #else
841         log_error("Forward-secure sealing not available.");
842         return -ENOTSUP;
843 #endif
844 }
845
846 static int verify(sd_journal *j) {
847         int r = 0;
848         Iterator i;
849         JournalFile *f;
850
851         assert(j);
852
853         log_show_color(true);
854
855         HASHMAP_FOREACH(f, j->files, i) {
856                 int k;
857                 usec_t first, validated, last;
858
859 #ifdef HAVE_GCRYPT
860                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
861                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
862 #endif
863
864                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
865                 if (k == -EINVAL) {
866                         /* If the key was invalid give up right-away. */
867                         return k;
868                 } else if (k < 0) {
869                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
870                         r = k;
871                 } else {
872                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
873                         log_info("PASS: %s", f->path);
874
875                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
876                                 if (validated > 0) {
877                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
878                                                  format_timestamp(a, sizeof(a), first),
879                                                  format_timestamp(b, sizeof(b), validated),
880                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
881                                 } else if (last > 0)
882                                         log_info("=> No sealing yet, %s of entries not sealed.",
883                                                  format_timespan(c, sizeof(c), last - first, 0));
884                                 else
885                                         log_info("=> No sealing yet, no entries in file.");
886                         }
887                 }
888         }
889
890         return r;
891 }
892
893 #ifdef HAVE_ACL
894 static int access_check_var_log_journal(sd_journal *j) {
895         _cleanup_strv_free_ char **g = NULL;
896         bool have_access;
897         int r;
898
899         assert(j);
900
901         have_access = in_group("systemd-journal") > 0;
902
903         if (!have_access) {
904                 /* Let's enumerate all groups from the default ACL of
905                  * the directory, which generally should allow access
906                  * to most journal files too */
907                 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
908                 if (r < 0)
909                         return r;
910         }
911
912         if (!have_access) {
913
914                 if (strv_isempty(g))
915                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
916                                    "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
917                                    "      turn off this notice.");
918                 else {
919                         _cleanup_free_ char *s = NULL;
920
921                         r = strv_extend(&g, "systemd-journal");
922                         if (r < 0)
923                                 return log_oom();
924
925                         strv_sort(g);
926                         strv_uniq(g);
927
928                         s = strv_join(g, "', '");
929                         if (!s)
930                                 return log_oom();
931
932                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
933                                    "      Users in the groups '%s' can see all messages.\n"
934                                    "      Pass -q to turn off this notice.", s);
935                 }
936         }
937
938         return 0;
939 }
940 #endif
941
942 static int access_check(sd_journal *j) {
943         Iterator it;
944         void *code;
945         int r = 0;
946
947         assert(j);
948
949         if (set_isempty(j->errors)) {
950                 if (hashmap_isempty(j->files))
951                         log_notice("No journal files were found.");
952                 return 0;
953         }
954
955         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
956 #ifdef HAVE_ACL
957                 /* If /var/log/journal doesn't even exist,
958                  * unprivileged users have no access at all */
959                 if (access("/var/log/journal", F_OK) < 0 &&
960                     geteuid() != 0 &&
961                     in_group("systemd-journal") <= 0) {
962                         log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
963                                   "enabled. Users in the 'systemd-journal' group may always access messages.");
964                         return -EACCES;
965                 }
966
967                 /* If /var/log/journal exists, try to pring a nice
968                    notice if the user lacks access to it */
969                 if (!arg_quiet && geteuid() != 0) {
970                         r = access_check_var_log_journal(j);
971                         if (r < 0)
972                                 return r;
973                 }
974 #else
975                 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
976                         log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
977                                   "group may access messages.");
978                         return -EACCES;
979                 }
980 #endif
981
982                 if (hashmap_isempty(j->files)) {
983                         log_error("No journal files were opened due to insufficient permissions.");
984                         r = -EACCES;
985                 }
986         }
987
988         SET_FOREACH(code, j->errors, it) {
989                 int err;
990
991                 err = -PTR_TO_INT(code);
992                 assert(err > 0);
993
994                 if (err != EACCES)
995                         log_warning("Error was encountered while opening journal files: %s",
996                                     strerror(err));
997         }
998
999         return r;
1000 }
1001
1002 int main(int argc, char *argv[]) {
1003         int r;
1004         sd_journal _cleanup_journal_close_ *j = NULL;
1005         bool need_seek = false;
1006         sd_id128_t previous_boot_id;
1007         bool previous_boot_id_valid = false, first_line = true;
1008         int n_shown = 0;
1009
1010         setlocale(LC_ALL, "");
1011         log_parse_environment();
1012         log_open();
1013
1014         r = parse_argv(argc, argv);
1015         if (r <= 0)
1016                 goto finish;
1017
1018         signal(SIGWINCH, columns_lines_cache_reset);
1019
1020         if (arg_action == ACTION_NEW_ID128) {
1021                 r = generate_new_id128();
1022                 goto finish;
1023         }
1024
1025         if (arg_action == ACTION_SETUP_KEYS) {
1026                 r = setup_keys();
1027                 goto finish;
1028         }
1029
1030         if (arg_action == ACTION_UPDATE_CATALOG ||
1031             arg_action == ACTION_LIST_CATALOG ||
1032             arg_action == ACTION_DUMP_CATALOG) {
1033
1034                 const char* database = CATALOG_DATABASE;
1035                 char _cleanup_free_ *copy = NULL;
1036                 if (arg_root) {
1037                         copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1038                         if (!copy) {
1039                                 r = log_oom();
1040                                 goto finish;
1041                         }
1042                         path_kill_slashes(copy);
1043                         database = copy;
1044                 }
1045
1046                 if (arg_action == ACTION_UPDATE_CATALOG) {
1047                         r = catalog_update(database, arg_root, catalog_file_dirs);
1048                         if (r < 0)
1049                                 log_error("Failed to list catalog: %s", strerror(-r));
1050                 } else {
1051                         bool oneline = arg_action == ACTION_LIST_CATALOG;
1052
1053                         if (optind < argc)
1054                                 r = catalog_list_items(stdout, database,
1055                                                        oneline, argv + optind);
1056                         else
1057                                 r = catalog_list(stdout, database, oneline);
1058                         if (r < 0)
1059                                 log_error("Failed to list catalog: %s", strerror(-r));
1060                 }
1061
1062                 goto finish;
1063         }
1064
1065         if (arg_directory)
1066                 r = sd_journal_open_directory(&j, arg_directory, 0);
1067         else
1068                 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
1069         if (r < 0) {
1070                 log_error("Failed to open journal: %s", strerror(-r));
1071                 return EXIT_FAILURE;
1072         }
1073
1074         r = access_check(j);
1075         if (r < 0)
1076                 return EXIT_FAILURE;
1077
1078         if (arg_action == ACTION_VERIFY) {
1079                 r = verify(j);
1080                 goto finish;
1081         }
1082
1083         if (arg_action == ACTION_PRINT_HEADER) {
1084                 journal_print_header(j);
1085                 return EXIT_SUCCESS;
1086         }
1087
1088         if (arg_action == ACTION_DISK_USAGE) {
1089                 uint64_t bytes;
1090                 char sbytes[FORMAT_BYTES_MAX];
1091
1092                 r = sd_journal_get_usage(j, &bytes);
1093                 if (r < 0)
1094                         return EXIT_FAILURE;
1095
1096                 printf("Journals take up %s on disk.\n",
1097                        format_bytes(sbytes, sizeof(sbytes), bytes));
1098                 return EXIT_SUCCESS;
1099         }
1100
1101         r = add_this_boot(j);
1102         if (r < 0)
1103                 return EXIT_FAILURE;
1104
1105         r = add_unit(j);
1106         if (r < 0)
1107                 return EXIT_FAILURE;
1108
1109         r = add_matches(j, argv + optind);
1110         if (r < 0)
1111                 return EXIT_FAILURE;
1112
1113         r = add_priorities(j);
1114         if (r < 0)
1115                 return EXIT_FAILURE;
1116
1117         /* Opening the fd now means the first sd_journal_wait() will actually wait */
1118         r = sd_journal_get_fd(j);
1119         if (r < 0)
1120                 return EXIT_FAILURE;
1121
1122         if (arg_field) {
1123                 const void *data;
1124                 size_t size;
1125
1126                 r = sd_journal_query_unique(j, arg_field);
1127                 if (r < 0) {
1128                         log_error("Failed to query unique data objects: %s", strerror(-r));
1129                         return EXIT_FAILURE;
1130                 }
1131
1132                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1133                         const void *eq;
1134
1135                         if (arg_lines >= 0 && n_shown >= arg_lines)
1136                                 break;
1137
1138                         eq = memchr(data, '=', size);
1139                         if (eq)
1140                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1141                         else
1142                                 printf("%.*s\n", (int) size, (const char*) data);
1143
1144                         n_shown ++;
1145                 }
1146
1147                 return EXIT_SUCCESS;
1148         }
1149
1150         if (arg_cursor) {
1151                 r = sd_journal_seek_cursor(j, arg_cursor);
1152                 if (r < 0) {
1153                         log_error("Failed to seek to cursor: %s", strerror(-r));
1154                         return EXIT_FAILURE;
1155                 }
1156                 if (!arg_reverse)
1157                         r = sd_journal_next(j);
1158                 else
1159                         r = sd_journal_previous(j);
1160
1161         } else if (arg_since_set && !arg_reverse) {
1162                 r = sd_journal_seek_realtime_usec(j, arg_since);
1163                 if (r < 0) {
1164                         log_error("Failed to seek to date: %s", strerror(-r));
1165                         return EXIT_FAILURE;
1166                 }
1167                 r = sd_journal_next(j);
1168
1169         } else if (arg_until_set && arg_reverse) {
1170                 r = sd_journal_seek_realtime_usec(j, arg_until);
1171                 if (r < 0) {
1172                         log_error("Failed to seek to date: %s", strerror(-r));
1173                         return EXIT_FAILURE;
1174                 }
1175                 r = sd_journal_previous(j);
1176
1177         } else if (arg_lines >= 0) {
1178                 r = sd_journal_seek_tail(j);
1179                 if (r < 0) {
1180                         log_error("Failed to seek to tail: %s", strerror(-r));
1181                         return EXIT_FAILURE;
1182                 }
1183
1184                 r = sd_journal_previous_skip(j, arg_lines);
1185
1186         } else if (arg_reverse) {
1187                 r = sd_journal_seek_tail(j);
1188                 if (r < 0) {
1189                         log_error("Failed to seek to tail: %s", strerror(-r));
1190                         return EXIT_FAILURE;
1191                 }
1192
1193                 r = sd_journal_previous(j);
1194
1195         } else {
1196                 r = sd_journal_seek_head(j);
1197                 if (r < 0) {
1198                         log_error("Failed to seek to head: %s", strerror(-r));
1199                         return EXIT_FAILURE;
1200                 }
1201
1202                 r = sd_journal_next(j);
1203         }
1204
1205         if (r < 0) {
1206                 log_error("Failed to iterate through journal: %s", strerror(-r));
1207                 return EXIT_FAILURE;
1208         }
1209
1210         if (!arg_no_pager && !arg_follow)
1211                 pager_open(arg_pager_end);
1212
1213         if (!arg_quiet) {
1214                 usec_t start, end;
1215                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1216
1217                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1218                 if (r < 0) {
1219                         log_error("Failed to get cutoff: %s", strerror(-r));
1220                         goto finish;
1221                 }
1222
1223                 if (r > 0) {
1224                         if (arg_follow)
1225                                 printf("-- Logs begin at %s. --\n",
1226                                        format_timestamp(start_buf, sizeof(start_buf), start));
1227                         else
1228                                 printf("-- Logs begin at %s, end at %s. --\n",
1229                                        format_timestamp(start_buf, sizeof(start_buf), start),
1230                                        format_timestamp(end_buf, sizeof(end_buf), end));
1231                 }
1232         }
1233
1234         for (;;) {
1235                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1236                         int flags;
1237
1238                         if (need_seek) {
1239                                 if (!arg_reverse)
1240                                         r = sd_journal_next(j);
1241                                 else
1242                                         r = sd_journal_previous(j);
1243                                 if (r < 0) {
1244                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1245                                         goto finish;
1246                                 }
1247                         }
1248
1249                         if (r == 0)
1250                                 break;
1251
1252                         if (arg_until_set && !arg_reverse) {
1253                                 usec_t usec;
1254
1255                                 r = sd_journal_get_realtime_usec(j, &usec);
1256                                 if (r < 0) {
1257                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1258                                         goto finish;
1259                                 }
1260                                 if (usec > arg_until)
1261                                         goto finish;
1262                         }
1263
1264                         if (arg_since_set && arg_reverse) {
1265                                 usec_t usec;
1266
1267                                 r = sd_journal_get_realtime_usec(j, &usec);
1268                                 if (r < 0) {
1269                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1270                                         goto finish;
1271                                 }
1272                                 if (usec < arg_since)
1273                                         goto finish;
1274                         }
1275
1276                         if (!arg_merge) {
1277                                 sd_id128_t boot_id;
1278
1279                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1280                                 if (r >= 0) {
1281                                         if (previous_boot_id_valid &&
1282                                             !sd_id128_equal(boot_id, previous_boot_id))
1283                                                 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1284
1285                                         previous_boot_id = boot_id;
1286                                         previous_boot_id_valid = true;
1287                                 }
1288                         }
1289
1290                         flags =
1291                                 arg_all * OUTPUT_SHOW_ALL |
1292                                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1293                                 on_tty() * OUTPUT_COLOR |
1294                                 arg_catalog * OUTPUT_CATALOG;
1295
1296                         r = output_journal(stdout, j, arg_output, 0, flags);
1297                         if (r < 0 || ferror(stdout))
1298                                 goto finish;
1299
1300                         need_seek = true;
1301                         n_shown++;
1302                 }
1303
1304                 if (!arg_follow)
1305                         break;
1306
1307                 r = sd_journal_wait(j, (uint64_t) -1);
1308                 if (r < 0) {
1309                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1310                         goto finish;
1311                 }
1312
1313                 first_line = false;
1314         }
1315
1316 finish:
1317         pager_close();
1318
1319         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1320 }