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