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