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