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