]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl.c
Remove unnecessary casts in printfs
[thirdparty/systemd.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 <fnmatch.h>
25 #include <errno.h>
26 #include <stddef.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.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 "fileio.h"
50 #include "build.h"
51 #include "pager.h"
52 #include "strv.h"
53 #include "set.h"
54 #include "journal-internal.h"
55 #include "journal-def.h"
56 #include "journal-verify.h"
57 #include "journal-authenticate.h"
58 #include "journal-qrcode.h"
59 #include "fsprg.h"
60 #include "unit-name.h"
61 #include "catalog.h"
62
63 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
64
65 static OutputMode arg_output = OUTPUT_SHORT;
66 static bool arg_pager_end = false;
67 static bool arg_follow = false;
68 static bool arg_full = true;
69 static bool arg_all = false;
70 static bool arg_no_pager = false;
71 static int arg_lines = -1;
72 static bool arg_no_tail = false;
73 static bool arg_quiet = false;
74 static bool arg_merge = false;
75 static bool arg_boot = false;
76 static sd_id128_t arg_boot_id = {};
77 static int arg_boot_offset = 0;
78 static bool arg_dmesg = false;
79 static const char *arg_cursor = NULL;
80 static const char *arg_after_cursor = NULL;
81 static bool arg_show_cursor = false;
82 static const char *arg_directory = NULL;
83 static char **arg_file = NULL;
84 static int arg_priorities = 0xFF;
85 static const char *arg_verify_key = NULL;
86 #ifdef HAVE_GCRYPT
87 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
88 static bool arg_force = false;
89 #endif
90 static usec_t arg_since, arg_until;
91 static bool arg_since_set = false, arg_until_set = false;
92 static char **arg_system_units = NULL;
93 static char **arg_user_units = NULL;
94 static const char *arg_field = NULL;
95 static bool arg_catalog = false;
96 static bool arg_reverse = false;
97 static int arg_journal_type = 0;
98 static const char *arg_root = NULL;
99 static const char *arg_machine = NULL;
100
101 static enum {
102 ACTION_SHOW,
103 ACTION_NEW_ID128,
104 ACTION_PRINT_HEADER,
105 ACTION_SETUP_KEYS,
106 ACTION_VERIFY,
107 ACTION_DISK_USAGE,
108 ACTION_LIST_CATALOG,
109 ACTION_DUMP_CATALOG,
110 ACTION_UPDATE_CATALOG,
111 ACTION_LIST_BOOTS,
112 } arg_action = ACTION_SHOW;
113
114 typedef struct boot_id_t {
115 sd_id128_t id;
116 uint64_t first;
117 uint64_t last;
118 } boot_id_t;
119
120 static void pager_open_if_enabled(void) {
121
122 if (arg_no_pager)
123 return;
124
125 pager_open(arg_pager_end);
126 }
127
128 static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) {
129 sd_id128_t id = SD_ID128_NULL;
130 int off = 0, r;
131
132 if (strlen(x) >= 32) {
133 char *t;
134
135 t = strndupa(x, 32);
136 r = sd_id128_from_string(t, &id);
137 if (r >= 0)
138 x += 32;
139
140 if (*x != '-' && *x != '+' && *x != 0)
141 return -EINVAL;
142
143 if (*x != 0) {
144 r = safe_atoi(x, &off);
145 if (r < 0)
146 return r;
147 }
148 } else {
149 r = safe_atoi(x, &off);
150 if (r < 0)
151 return r;
152 }
153
154 if (boot_id)
155 *boot_id = id;
156
157 if (offset)
158 *offset = off;
159
160 return 0;
161 }
162
163 static int help(void) {
164
165 pager_open_if_enabled();
166
167 printf("%s [OPTIONS...] [MATCHES...]\n\n"
168 "Query the journal.\n\n"
169 "Flags:\n"
170 " --system Show only the system journal\n"
171 " --user Show only the user journal for the current user\n"
172 " -M --machine=CONTAINER Operate on local container\n"
173 " --since=DATE Start showing entries on or newer than the specified date\n"
174 " --until=DATE Stop showing entries on or older than the specified date\n"
175 " -c --cursor=CURSOR Start showing entries from the specified cursor\n"
176 " --after-cursor=CURSOR Start showing entries from after the specified cursor\n"
177 " --show-cursor Print the cursor after all the entries\n"
178 " -b --boot[=ID] Show data only from ID or, if unspecified, the current boot\n"
179 " --list-boots Show terse information about recorded boots\n"
180 " -k --dmesg Show kernel message log from the current boot\n"
181 " -u --unit=UNIT Show data only from the specified unit\n"
182 " --user-unit=UNIT Show data only from the specified user session unit\n"
183 " -p --priority=RANGE Show only messages within the specified priority range\n"
184 " -e --pager-end Immediately jump to end of the journal in the pager\n"
185 " -f --follow Follow the journal\n"
186 " -n --lines[=INTEGER] Number of journal entries to show\n"
187 " --no-tail Show all lines, even in follow mode\n"
188 " -r --reverse Show the newest entries first\n"
189 " -o --output=STRING Change journal output mode (short, short-iso,\n"
190 " short-precise, short-monotonic, verbose,\n"
191 " export, json, json-pretty, json-sse, cat)\n"
192 " -x --catalog Add message explanations where available\n"
193 " --no-full Ellipsize fields\n"
194 " -a --all Show all fields, including long and unprintable\n"
195 " -q --quiet Do not show privilege warning\n"
196 " --no-pager Do not pipe output into a pager\n"
197 " -m --merge Show entries from all available journals\n"
198 " -D --directory=PATH Show journal files from directory\n"
199 " --file=PATH Show journal file\n"
200 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
201 #ifdef HAVE_GCRYPT
202 " --interval=TIME Time interval for changing the FSS sealing key\n"
203 " --verify-key=KEY Specify FSS verification key\n"
204 " --force Force overriding of the FSS key pair with --setup-keys\n"
205 #endif
206 "\nCommands:\n"
207 " -h --help Show this help text\n"
208 " --version Show package version\n"
209 " --new-id128 Generate a new 128-bit ID\n"
210 " --header Show journal header information\n"
211 " --disk-usage Show total disk usage of all journal files\n"
212 " -F --field=FIELD List all values that a specified field takes\n"
213 " --list-catalog Show message IDs of all entries in the message catalog\n"
214 " --dump-catalog Show entries in the message catalog\n"
215 " --update-catalog Update the message catalog database\n"
216 #ifdef HAVE_GCRYPT
217 " --setup-keys Generate a new FSS key pair\n"
218 " --verify Verify journal file consistency\n"
219 #endif
220 , program_invocation_short_name);
221
222 return 0;
223 }
224
225 static int parse_argv(int argc, char *argv[]) {
226
227 enum {
228 ARG_VERSION = 0x100,
229 ARG_NO_PAGER,
230 ARG_NO_FULL,
231 ARG_NO_TAIL,
232 ARG_NEW_ID128,
233 ARG_LIST_BOOTS,
234 ARG_USER,
235 ARG_SYSTEM,
236 ARG_ROOT,
237 ARG_HEADER,
238 ARG_SETUP_KEYS,
239 ARG_FILE,
240 ARG_INTERVAL,
241 ARG_VERIFY,
242 ARG_VERIFY_KEY,
243 ARG_DISK_USAGE,
244 ARG_SINCE,
245 ARG_UNTIL,
246 ARG_AFTER_CURSOR,
247 ARG_SHOW_CURSOR,
248 ARG_USER_UNIT,
249 ARG_LIST_CATALOG,
250 ARG_DUMP_CATALOG,
251 ARG_UPDATE_CATALOG,
252 ARG_FORCE,
253 };
254
255 static const struct option options[] = {
256 { "help", no_argument, NULL, 'h' },
257 { "version" , no_argument, NULL, ARG_VERSION },
258 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
259 { "pager-end", no_argument, NULL, 'e' },
260 { "follow", no_argument, NULL, 'f' },
261 { "force", no_argument, NULL, ARG_FORCE },
262 { "output", required_argument, NULL, 'o' },
263 { "all", no_argument, NULL, 'a' },
264 { "full", no_argument, NULL, 'l' },
265 { "no-full", no_argument, NULL, ARG_NO_FULL },
266 { "lines", optional_argument, NULL, 'n' },
267 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
268 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
269 { "quiet", no_argument, NULL, 'q' },
270 { "merge", no_argument, NULL, 'm' },
271 { "boot", optional_argument, NULL, 'b' },
272 { "list-boots", no_argument, NULL, ARG_LIST_BOOTS },
273 { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */
274 { "dmesg", no_argument, NULL, 'k' },
275 { "system", no_argument, NULL, ARG_SYSTEM },
276 { "user", no_argument, NULL, ARG_USER },
277 { "directory", required_argument, NULL, 'D' },
278 { "file", required_argument, NULL, ARG_FILE },
279 { "root", required_argument, NULL, ARG_ROOT },
280 { "header", no_argument, NULL, ARG_HEADER },
281 { "priority", required_argument, NULL, 'p' },
282 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
283 { "interval", required_argument, NULL, ARG_INTERVAL },
284 { "verify", no_argument, NULL, ARG_VERIFY },
285 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
286 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
287 { "cursor", required_argument, NULL, 'c' },
288 { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
289 { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
290 { "since", required_argument, NULL, ARG_SINCE },
291 { "until", required_argument, NULL, ARG_UNTIL },
292 { "unit", required_argument, NULL, 'u' },
293 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
294 { "field", required_argument, NULL, 'F' },
295 { "catalog", no_argument, NULL, 'x' },
296 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
297 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
298 { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
299 { "reverse", no_argument, NULL, 'r' },
300 { "machine", required_argument, NULL, 'M' },
301 {}
302 };
303
304 int c, r;
305
306 assert(argc >= 0);
307 assert(argv);
308
309 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xrM:", options, NULL)) >= 0) {
310
311 switch (c) {
312
313 case 'h':
314 return help();
315
316 case ARG_VERSION:
317 puts(PACKAGE_STRING);
318 puts(SYSTEMD_FEATURES);
319 return 0;
320
321 case ARG_NO_PAGER:
322 arg_no_pager = true;
323 break;
324
325 case 'e':
326 arg_pager_end = true;
327
328 if (arg_lines < 0)
329 arg_lines = 1000;
330
331 break;
332
333 case 'f':
334 arg_follow = true;
335 break;
336
337 case 'o':
338 arg_output = output_mode_from_string(optarg);
339 if (arg_output < 0) {
340 log_error("Unknown output format '%s'.", optarg);
341 return -EINVAL;
342 }
343
344 if (arg_output == OUTPUT_EXPORT ||
345 arg_output == OUTPUT_JSON ||
346 arg_output == OUTPUT_JSON_PRETTY ||
347 arg_output == OUTPUT_JSON_SSE ||
348 arg_output == OUTPUT_CAT)
349 arg_quiet = true;
350
351 break;
352
353 case 'l':
354 arg_full = true;
355 break;
356
357 case ARG_NO_FULL:
358 arg_full = false;
359 break;
360
361 case 'a':
362 arg_all = true;
363 break;
364
365 case 'n':
366 if (optarg) {
367 r = safe_atoi(optarg, &arg_lines);
368 if (r < 0 || arg_lines < 0) {
369 log_error("Failed to parse lines '%s'", optarg);
370 return -EINVAL;
371 }
372 } else {
373 int n;
374
375 /* Hmm, no argument? Maybe the next
376 * word on the command line is
377 * supposed to be the argument? Let's
378 * see if there is one, and is
379 * parsable as a positive
380 * integer... */
381
382 if (optind < argc &&
383 safe_atoi(argv[optind], &n) >= 0 &&
384 n >= 0) {
385
386 arg_lines = n;
387 optind++;
388 } else
389 arg_lines = 10;
390 }
391
392 break;
393
394 case ARG_NO_TAIL:
395 arg_no_tail = true;
396 break;
397
398 case ARG_NEW_ID128:
399 arg_action = ACTION_NEW_ID128;
400 break;
401
402 case 'q':
403 arg_quiet = true;
404 break;
405
406 case 'm':
407 arg_merge = true;
408 break;
409
410 case 'b':
411 arg_boot = true;
412
413 if (optarg) {
414 r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
415 if (r < 0) {
416 log_error("Failed to parse boot descriptor '%s'", optarg);
417 return -EINVAL;
418 }
419 } else {
420
421 /* Hmm, no argument? Maybe the next
422 * word on the command line is
423 * supposed to be the argument? Let's
424 * see if there is one and is parsable
425 * as a boot descriptor... */
426
427 if (optind < argc &&
428 parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset) >= 0)
429 optind++;
430 }
431
432 break;
433
434 case ARG_LIST_BOOTS:
435 arg_action = ACTION_LIST_BOOTS;
436 break;
437
438 case 'k':
439 arg_boot = arg_dmesg = true;
440 break;
441
442 case ARG_SYSTEM:
443 arg_journal_type |= SD_JOURNAL_SYSTEM;
444 break;
445
446 case ARG_USER:
447 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
448 break;
449
450 case 'M':
451 arg_machine = optarg;
452 break;
453
454 case 'D':
455 arg_directory = optarg;
456 break;
457
458 case ARG_FILE:
459 r = glob_extend(&arg_file, optarg);
460 if (r < 0) {
461 log_error("Failed to add paths: %s", strerror(-r));
462 return r;
463 };
464 break;
465
466 case ARG_ROOT:
467 arg_root = optarg;
468 break;
469
470 case 'c':
471 arg_cursor = optarg;
472 break;
473
474 case ARG_AFTER_CURSOR:
475 arg_after_cursor = optarg;
476 break;
477
478 case ARG_SHOW_CURSOR:
479 arg_show_cursor = true;
480 break;
481
482 case ARG_HEADER:
483 arg_action = ACTION_PRINT_HEADER;
484 break;
485
486 case ARG_VERIFY:
487 arg_action = ACTION_VERIFY;
488 break;
489
490 case ARG_DISK_USAGE:
491 arg_action = ACTION_DISK_USAGE;
492 break;
493
494 #ifdef HAVE_GCRYPT
495 case ARG_FORCE:
496 arg_force = true;
497 break;
498
499 case ARG_SETUP_KEYS:
500 arg_action = ACTION_SETUP_KEYS;
501 break;
502
503
504 case ARG_VERIFY_KEY:
505 arg_action = ACTION_VERIFY;
506 arg_verify_key = optarg;
507 arg_merge = false;
508 break;
509
510 case ARG_INTERVAL:
511 r = parse_sec(optarg, &arg_interval);
512 if (r < 0 || arg_interval <= 0) {
513 log_error("Failed to parse sealing key change interval: %s", optarg);
514 return -EINVAL;
515 }
516 break;
517 #else
518 case ARG_SETUP_KEYS:
519 case ARG_VERIFY_KEY:
520 case ARG_INTERVAL:
521 case ARG_FORCE:
522 log_error("Forward-secure sealing not available.");
523 return -ENOTSUP;
524 #endif
525
526 case 'p': {
527 const char *dots;
528
529 dots = strstr(optarg, "..");
530 if (dots) {
531 char *a;
532 int from, to, i;
533
534 /* a range */
535 a = strndup(optarg, dots - optarg);
536 if (!a)
537 return log_oom();
538
539 from = log_level_from_string(a);
540 to = log_level_from_string(dots + 2);
541 free(a);
542
543 if (from < 0 || to < 0) {
544 log_error("Failed to parse log level range %s", optarg);
545 return -EINVAL;
546 }
547
548 arg_priorities = 0;
549
550 if (from < to) {
551 for (i = from; i <= to; i++)
552 arg_priorities |= 1 << i;
553 } else {
554 for (i = to; i <= from; i++)
555 arg_priorities |= 1 << i;
556 }
557
558 } else {
559 int p, i;
560
561 p = log_level_from_string(optarg);
562 if (p < 0) {
563 log_error("Unknown log level %s", optarg);
564 return -EINVAL;
565 }
566
567 arg_priorities = 0;
568
569 for (i = 0; i <= p; i++)
570 arg_priorities |= 1 << i;
571 }
572
573 break;
574 }
575
576 case ARG_SINCE:
577 r = parse_timestamp(optarg, &arg_since);
578 if (r < 0) {
579 log_error("Failed to parse timestamp: %s", optarg);
580 return -EINVAL;
581 }
582 arg_since_set = true;
583 break;
584
585 case ARG_UNTIL:
586 r = parse_timestamp(optarg, &arg_until);
587 if (r < 0) {
588 log_error("Failed to parse timestamp: %s", optarg);
589 return -EINVAL;
590 }
591 arg_until_set = true;
592 break;
593
594 case 'u':
595 r = strv_extend(&arg_system_units, optarg);
596 if (r < 0)
597 return log_oom();
598 break;
599
600 case ARG_USER_UNIT:
601 r = strv_extend(&arg_user_units, optarg);
602 if (r < 0)
603 return log_oom();
604 break;
605
606 case 'F':
607 arg_field = optarg;
608 break;
609
610 case 'x':
611 arg_catalog = true;
612 break;
613
614 case ARG_LIST_CATALOG:
615 arg_action = ACTION_LIST_CATALOG;
616 break;
617
618 case ARG_DUMP_CATALOG:
619 arg_action = ACTION_DUMP_CATALOG;
620 break;
621
622 case ARG_UPDATE_CATALOG:
623 arg_action = ACTION_UPDATE_CATALOG;
624 break;
625
626 case 'r':
627 arg_reverse = true;
628 break;
629
630 case '?':
631 return -EINVAL;
632
633 default:
634 assert_not_reached("Unhandled option");
635 }
636 }
637
638 if (arg_follow && !arg_no_tail && arg_lines < 0)
639 arg_lines = 10;
640
641 if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
642 log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
643 return -EINVAL;
644 }
645
646 if (arg_since_set && arg_until_set && arg_since > arg_until) {
647 log_error("--since= must be before --until=.");
648 return -EINVAL;
649 }
650
651 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
652 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
653 return -EINVAL;
654 }
655
656 if (arg_follow && arg_reverse) {
657 log_error("Please specify either --reverse= or --follow=, not both.");
658 return -EINVAL;
659 }
660
661 if (arg_action != ACTION_SHOW && optind < argc) {
662 log_error("Extraneous arguments starting with '%s'", argv[optind]);
663 return -EINVAL;
664 }
665
666 return 1;
667 }
668
669 static int generate_new_id128(void) {
670 sd_id128_t id;
671 int r;
672 unsigned i;
673
674 r = sd_id128_randomize(&id);
675 if (r < 0) {
676 log_error("Failed to generate ID: %s", strerror(-r));
677 return r;
678 }
679
680 printf("As string:\n"
681 SD_ID128_FORMAT_STR "\n\n"
682 "As UUID:\n"
683 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
684 "As macro:\n"
685 "#define MESSAGE_XYZ SD_ID128_MAKE(",
686 SD_ID128_FORMAT_VAL(id),
687 SD_ID128_FORMAT_VAL(id));
688 for (i = 0; i < 16; i++)
689 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
690 fputs(")\n\n", stdout);
691
692 printf("As Python constant:\n"
693 ">>> import uuid\n"
694 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
695 SD_ID128_FORMAT_VAL(id));
696
697 return 0;
698 }
699
700 static int add_matches(sd_journal *j, char **args) {
701 char **i;
702
703 assert(j);
704
705 STRV_FOREACH(i, args) {
706 int r;
707
708 if (streq(*i, "+"))
709 r = sd_journal_add_disjunction(j);
710 else if (path_is_absolute(*i)) {
711 _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
712 const char *path;
713 _cleanup_free_ char *interpreter = NULL;
714 struct stat st;
715
716 p = canonicalize_file_name(*i);
717 path = p ? p : *i;
718
719 if (stat(path, &st) < 0) {
720 log_error("Couldn't stat file: %m");
721 return -errno;
722 }
723
724 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
725 if (executable_is_script(path, &interpreter) > 0) {
726 _cleanup_free_ char *comm;
727
728 comm = strndup(basename(path), 15);
729 if (!comm)
730 return log_oom();
731
732 t = strappend("_COMM=", comm);
733
734 /* Append _EXE only if the interpreter is not a link.
735 Otherwise, it might be outdated often. */
736 if (lstat(interpreter, &st) == 0 &&
737 !S_ISLNK(st.st_mode)) {
738 t2 = strappend("_EXE=", interpreter);
739 if (!t2)
740 return log_oom();
741 }
742 } else
743 t = strappend("_EXE=", path);
744 } else if (S_ISCHR(st.st_mode))
745 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
746 else if (S_ISBLK(st.st_mode))
747 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
748 else {
749 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
750 return -EINVAL;
751 }
752
753 if (!t)
754 return log_oom();
755
756 r = sd_journal_add_match(j, t, 0);
757 if (t2)
758 r = sd_journal_add_match(j, t2, 0);
759 } else
760 r = sd_journal_add_match(j, *i, 0);
761
762 if (r < 0) {
763 log_error("Failed to add match '%s': %s", *i, strerror(-r));
764 return r;
765 }
766 }
767
768 return 0;
769 }
770
771 static int boot_id_cmp(const void *a, const void *b) {
772 uint64_t _a, _b;
773
774 _a = ((const boot_id_t *)a)->first;
775 _b = ((const boot_id_t *)b)->first;
776
777 return _a < _b ? -1 : (_a > _b ? 1 : 0);
778 }
779
780 static int list_boots(sd_journal *j) {
781 int r;
782 const void *data;
783 unsigned int count = 0;
784 int w, i;
785 size_t length, allocated = 0;
786 boot_id_t *id;
787 _cleanup_free_ boot_id_t *all_ids = NULL;
788
789 r = sd_journal_query_unique(j, "_BOOT_ID");
790 if (r < 0)
791 return r;
792
793 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
794 if (length < strlen("_BOOT_ID="))
795 continue;
796
797 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
798 return log_oom();
799
800 id = &all_ids[count];
801
802 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
803 if (r < 0)
804 continue;
805
806 r = sd_journal_add_match(j, data, length);
807 if (r < 0)
808 return r;
809
810 r = sd_journal_seek_head(j);
811 if (r < 0)
812 return r;
813
814 r = sd_journal_next(j);
815 if (r < 0)
816 return r;
817 else if (r == 0)
818 goto flush;
819
820 r = sd_journal_get_realtime_usec(j, &id->first);
821 if (r < 0)
822 return r;
823
824 r = sd_journal_seek_tail(j);
825 if (r < 0)
826 return r;
827
828 r = sd_journal_previous(j);
829 if (r < 0)
830 return r;
831 else if (r == 0)
832 goto flush;
833
834 r = sd_journal_get_realtime_usec(j, &id->last);
835 if (r < 0)
836 return r;
837
838 count++;
839 flush:
840 sd_journal_flush_matches(j);
841 }
842
843 qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
844
845 /* numbers are one less, but we need an extra char for the sign */
846 w = DECIMAL_STR_WIDTH(count - 1) + 1;
847
848 for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
849 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
850
851 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
852 w, i - count + 1,
853 SD_ID128_FORMAT_VAL(id->id),
854 format_timestamp(a, sizeof(a), id->first),
855 format_timestamp(b, sizeof(b), id->last));
856 }
857
858 return 0;
859 }
860
861 static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
862 int r;
863 const void *data;
864 unsigned int count = 0;
865 size_t length, allocated = 0;
866 boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
867 _cleanup_free_ boot_id_t *all_ids = NULL;
868
869 assert(j);
870 assert(boot_id);
871
872 r = sd_journal_query_unique(j, "_BOOT_ID");
873 if (r < 0)
874 return r;
875
876 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
877 if (length < strlen("_BOOT_ID="))
878 continue;
879
880 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
881 return log_oom();
882
883 id = &all_ids[count];
884
885 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
886 if (r < 0)
887 continue;
888
889 r = sd_journal_add_match(j, data, length);
890 if (r < 0)
891 return r;
892
893 r = sd_journal_seek_head(j);
894 if (r < 0)
895 return r;
896
897 r = sd_journal_next(j);
898 if (r < 0)
899 return r;
900 else if (r == 0)
901 goto flush;
902
903 r = sd_journal_get_realtime_usec(j, &id->first);
904 if (r < 0)
905 return r;
906
907 if (sd_id128_equal(id->id, *boot_id))
908 ref_boot_id = *id;
909
910 count++;
911 flush:
912 sd_journal_flush_matches(j);
913 }
914
915 qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
916
917 if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
918 if (relative > (int) count || relative <= -(int)count)
919 return -EADDRNOTAVAIL;
920
921 *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
922 } else {
923 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
924
925 if (!id ||
926 relative <= 0 ? (id - all_ids) + relative < 0 :
927 (id - all_ids) + relative >= (int) count)
928 return -EADDRNOTAVAIL;
929
930 *boot_id = (id + relative)->id;
931 }
932
933 return 0;
934 }
935
936 static int add_boot(sd_journal *j) {
937 char match[9+32+1] = "_BOOT_ID=";
938 int r;
939
940 assert(j);
941
942 if (!arg_boot)
943 return 0;
944
945 if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
946 return add_match_this_boot(j, arg_machine);
947
948 r = get_relative_boot_id(j, &arg_boot_id, arg_boot_offset);
949 if (r < 0) {
950 if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
951 log_error("Failed to look up boot %+i: %s", arg_boot_offset, strerror(-r));
952 else
953 log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
954 SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, strerror(-r));
955 return r;
956 }
957
958 sd_id128_to_string(arg_boot_id, match + 9);
959
960 r = sd_journal_add_match(j, match, sizeof(match) - 1);
961 if (r < 0) {
962 log_error("Failed to add match: %s", strerror(-r));
963 return r;
964 }
965
966 r = sd_journal_add_conjunction(j);
967 if (r < 0)
968 return r;
969
970 return 0;
971 }
972
973 static int add_dmesg(sd_journal *j) {
974 int r;
975 assert(j);
976
977 if (!arg_dmesg)
978 return 0;
979
980 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
981 if (r < 0) {
982 log_error("Failed to add match: %s", strerror(-r));
983 return r;
984 }
985
986 r = sd_journal_add_conjunction(j);
987 if (r < 0)
988 return r;
989
990 return 0;
991 }
992
993 static int get_possible_units(sd_journal *j,
994 const char *fields,
995 char **patterns,
996 Set **units) {
997 _cleanup_set_free_free_ Set *found;
998 const char *field;
999 int r;
1000
1001 found = set_new(string_hash_func, string_compare_func);
1002 if (!found)
1003 return log_oom();
1004
1005 NULSTR_FOREACH(field, fields) {
1006 const void *data;
1007 size_t size;
1008
1009 r = sd_journal_query_unique(j, field);
1010 if (r < 0)
1011 return r;
1012
1013 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1014 char **pattern, *eq;
1015 size_t prefix;
1016 _cleanup_free_ char *u = NULL;
1017
1018 eq = memchr(data, '=', size);
1019 if (eq)
1020 prefix = eq - (char*) data + 1;
1021 else
1022 prefix = 0;
1023
1024 u = strndup((char*) data + prefix, size - prefix);
1025 if (!u)
1026 return log_oom();
1027
1028 STRV_FOREACH(pattern, patterns)
1029 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1030 log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1031
1032 r = set_consume(found, u);
1033 u = NULL;
1034 if (r < 0 && r != -EEXIST)
1035 return r;
1036
1037 break;
1038 }
1039 }
1040 }
1041
1042 *units = found;
1043 found = NULL;
1044 return 0;
1045 }
1046
1047 /* This list is supposed to return the superset of unit names
1048 * possibly matched by rules added with add_matches_for_unit... */
1049 #define SYSTEM_UNITS \
1050 "_SYSTEMD_UNIT\0" \
1051 "COREDUMP_UNIT\0" \
1052 "UNIT\0" \
1053 "OBJECT_SYSTEMD_UNIT\0" \
1054 "_SYSTEMD_SLICE\0"
1055
1056 /* ... and add_matches_for_user_unit */
1057 #define USER_UNITS \
1058 "_SYSTEMD_USER_UNIT\0" \
1059 "USER_UNIT\0" \
1060 "COREDUMP_USER_UNIT\0" \
1061 "OBJECT_SYSTEMD_USER_UNIT\0"
1062
1063 static int add_units(sd_journal *j) {
1064 _cleanup_strv_free_ char **patterns = NULL;
1065 int r, count = 0;
1066 char **i;
1067
1068 assert(j);
1069
1070 STRV_FOREACH(i, arg_system_units) {
1071 _cleanup_free_ char *u = NULL;
1072
1073 u = unit_name_mangle(*i, MANGLE_GLOB);
1074 if (!u)
1075 return log_oom();
1076
1077 if (string_is_glob(u)) {
1078 r = strv_push(&patterns, u);
1079 if (r < 0)
1080 return r;
1081 u = NULL;
1082 } else {
1083 r = add_matches_for_unit(j, u);
1084 if (r < 0)
1085 return r;
1086 r = sd_journal_add_disjunction(j);
1087 if (r < 0)
1088 return r;
1089 count ++;
1090 }
1091 }
1092
1093 if (!strv_isempty(patterns)) {
1094 _cleanup_set_free_free_ Set *units = NULL;
1095 Iterator it;
1096 char *u;
1097
1098 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1099 if (r < 0)
1100 return r;
1101
1102 SET_FOREACH(u, units, it) {
1103 r = add_matches_for_unit(j, u);
1104 if (r < 0)
1105 return r;
1106 r = sd_journal_add_disjunction(j);
1107 if (r < 0)
1108 return r;
1109 count ++;
1110 }
1111 }
1112
1113 strv_free(patterns);
1114 patterns = NULL;
1115
1116 STRV_FOREACH(i, arg_user_units) {
1117 _cleanup_free_ char *u = NULL;
1118
1119 u = unit_name_mangle(*i, MANGLE_GLOB);
1120 if (!u)
1121 return log_oom();
1122
1123 if (string_is_glob(u)) {
1124 r = strv_push(&patterns, u);
1125 if (r < 0)
1126 return r;
1127 u = NULL;
1128 } else {
1129 r = add_matches_for_user_unit(j, u, getuid());
1130 if (r < 0)
1131 return r;
1132 r = sd_journal_add_disjunction(j);
1133 if (r < 0)
1134 return r;
1135 count ++;
1136 }
1137 }
1138
1139 if (!strv_isempty(patterns)) {
1140 _cleanup_set_free_free_ Set *units = NULL;
1141 Iterator it;
1142 char *u;
1143
1144 r = get_possible_units(j, USER_UNITS, patterns, &units);
1145 if (r < 0)
1146 return r;
1147
1148 SET_FOREACH(u, units, it) {
1149 r = add_matches_for_user_unit(j, u, getuid());
1150 if (r < 0)
1151 return r;
1152 r = sd_journal_add_disjunction(j);
1153 if (r < 0)
1154 return r;
1155 count ++;
1156 }
1157 }
1158
1159 /* Complain if the user request matches but nothing whatsoever was
1160 * found, since otherwise everything would be matched. */
1161 if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1162 return -ENODATA;
1163
1164 r = sd_journal_add_conjunction(j);
1165 if (r < 0)
1166 return r;
1167
1168 return 0;
1169 }
1170
1171 static int add_priorities(sd_journal *j) {
1172 char match[] = "PRIORITY=0";
1173 int i, r;
1174 assert(j);
1175
1176 if (arg_priorities == 0xFF)
1177 return 0;
1178
1179 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1180 if (arg_priorities & (1 << i)) {
1181 match[sizeof(match)-2] = '0' + i;
1182
1183 r = sd_journal_add_match(j, match, strlen(match));
1184 if (r < 0) {
1185 log_error("Failed to add match: %s", strerror(-r));
1186 return r;
1187 }
1188 }
1189
1190 r = sd_journal_add_conjunction(j);
1191 if (r < 0)
1192 return r;
1193
1194 return 0;
1195 }
1196
1197 static int setup_keys(void) {
1198 #ifdef HAVE_GCRYPT
1199 size_t mpk_size, seed_size, state_size, i;
1200 uint8_t *mpk, *seed, *state;
1201 ssize_t l;
1202 int fd = -1, r, attr = 0;
1203 sd_id128_t machine, boot;
1204 char *p = NULL, *k = NULL;
1205 struct FSSHeader h;
1206 uint64_t n;
1207 struct stat st;
1208
1209 r = stat("/var/log/journal", &st);
1210 if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
1211 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
1212 return -errno;
1213 }
1214
1215 if (r < 0 || !S_ISDIR(st.st_mode)) {
1216 log_error("%s is not a directory, must be using persistent logging for FSS.",
1217 "/var/log/journal");
1218 return r < 0 ? -errno : -ENOTDIR;
1219 }
1220
1221 r = sd_id128_get_machine(&machine);
1222 if (r < 0) {
1223 log_error("Failed to get machine ID: %s", strerror(-r));
1224 return r;
1225 }
1226
1227 r = sd_id128_get_boot(&boot);
1228 if (r < 0) {
1229 log_error("Failed to get boot ID: %s", strerror(-r));
1230 return r;
1231 }
1232
1233 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1234 SD_ID128_FORMAT_VAL(machine)) < 0)
1235 return log_oom();
1236
1237 if (access(p, F_OK) >= 0) {
1238 if (arg_force) {
1239 r = unlink(p);
1240 if (r < 0) {
1241 log_error("unlink(\"%s\") failed: %m", p);
1242 r = -errno;
1243 goto finish;
1244 }
1245 } else {
1246 log_error("Sealing key file %s exists already. (--force to recreate)", p);
1247 r = -EEXIST;
1248 goto finish;
1249 }
1250 }
1251
1252 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1253 SD_ID128_FORMAT_VAL(machine)) < 0) {
1254 r = log_oom();
1255 goto finish;
1256 }
1257
1258 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1259 mpk = alloca(mpk_size);
1260
1261 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1262 seed = alloca(seed_size);
1263
1264 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1265 state = alloca(state_size);
1266
1267 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1268 if (fd < 0) {
1269 log_error("Failed to open /dev/random: %m");
1270 r = -errno;
1271 goto finish;
1272 }
1273
1274 log_info("Generating seed...");
1275 l = loop_read(fd, seed, seed_size, true);
1276 if (l < 0 || (size_t) l != seed_size) {
1277 log_error("Failed to read random seed: %s", strerror(EIO));
1278 r = -EIO;
1279 goto finish;
1280 }
1281
1282 log_info("Generating key pair...");
1283 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1284
1285 log_info("Generating sealing key...");
1286 FSPRG_GenState0(state, mpk, seed, seed_size);
1287
1288 assert(arg_interval > 0);
1289
1290 n = now(CLOCK_REALTIME);
1291 n /= arg_interval;
1292
1293 safe_close(fd);
1294 fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1295 if (fd < 0) {
1296 log_error("Failed to open %s: %m", k);
1297 r = -errno;
1298 goto finish;
1299 }
1300
1301 /* Enable secure remove, exclusion from dump, synchronous
1302 * writing and in-place updating */
1303 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
1304 log_warning("FS_IOC_GETFLAGS failed: %m");
1305
1306 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1307
1308 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1309 log_warning("FS_IOC_SETFLAGS failed: %m");
1310
1311 zero(h);
1312 memcpy(h.signature, "KSHHRHLP", 8);
1313 h.machine_id = machine;
1314 h.boot_id = boot;
1315 h.header_size = htole64(sizeof(h));
1316 h.start_usec = htole64(n * arg_interval);
1317 h.interval_usec = htole64(arg_interval);
1318 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1319 h.fsprg_state_size = htole64(state_size);
1320
1321 l = loop_write(fd, &h, sizeof(h), false);
1322 if (l < 0 || (size_t) l != sizeof(h)) {
1323 log_error("Failed to write header: %s", strerror(EIO));
1324 r = -EIO;
1325 goto finish;
1326 }
1327
1328 l = loop_write(fd, state, state_size, false);
1329 if (l < 0 || (size_t) l != state_size) {
1330 log_error("Failed to write state: %s", strerror(EIO));
1331 r = -EIO;
1332 goto finish;
1333 }
1334
1335 if (link(k, p) < 0) {
1336 log_error("Failed to link file: %m");
1337 r = -errno;
1338 goto finish;
1339 }
1340
1341 if (on_tty()) {
1342 fprintf(stderr,
1343 "\n"
1344 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
1345 "the following local file. This key file is automatically updated when the\n"
1346 "sealing key is advanced. It should not be used on multiple hosts.\n"
1347 "\n"
1348 "\t%s\n"
1349 "\n"
1350 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
1351 "at a safe location and should not be saved locally on disk.\n"
1352 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
1353 fflush(stderr);
1354 }
1355 for (i = 0; i < seed_size; i++) {
1356 if (i > 0 && i % 3 == 0)
1357 putchar('-');
1358 printf("%02x", ((uint8_t*) seed)[i]);
1359 }
1360
1361 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1362
1363 if (on_tty()) {
1364 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1365
1366 fprintf(stderr,
1367 ANSI_HIGHLIGHT_OFF "\n"
1368 "The sealing key is automatically changed every %s.\n",
1369 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1370
1371 hn = gethostname_malloc();
1372
1373 if (hn) {
1374 hostname_cleanup(hn, false);
1375 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1376 } else
1377 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1378
1379 #ifdef HAVE_QRENCODE
1380 /* If this is not an UTF-8 system don't print any QR codes */
1381 if (is_locale_utf8()) {
1382 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1383 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1384 }
1385 #endif
1386 free(hn);
1387 }
1388
1389 r = 0;
1390
1391 finish:
1392 safe_close(fd);
1393
1394 if (k) {
1395 unlink(k);
1396 free(k);
1397 }
1398
1399 free(p);
1400
1401 return r;
1402 #else
1403 log_error("Forward-secure sealing not available.");
1404 return -ENOTSUP;
1405 #endif
1406 }
1407
1408 static int verify(sd_journal *j) {
1409 int r = 0;
1410 Iterator i;
1411 JournalFile *f;
1412
1413 assert(j);
1414
1415 log_show_color(true);
1416
1417 HASHMAP_FOREACH(f, j->files, i) {
1418 int k;
1419 usec_t first, validated, last;
1420
1421 #ifdef HAVE_GCRYPT
1422 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1423 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1424 #endif
1425
1426 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1427 if (k == -EINVAL) {
1428 /* If the key was invalid give up right-away. */
1429 return k;
1430 } else if (k < 0) {
1431 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1432 r = k;
1433 } else {
1434 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1435 log_info("PASS: %s", f->path);
1436
1437 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1438 if (validated > 0) {
1439 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1440 format_timestamp(a, sizeof(a), first),
1441 format_timestamp(b, sizeof(b), validated),
1442 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1443 } else if (last > 0)
1444 log_info("=> No sealing yet, %s of entries not sealed.",
1445 format_timespan(c, sizeof(c), last - first, 0));
1446 else
1447 log_info("=> No sealing yet, no entries in file.");
1448 }
1449 }
1450 }
1451
1452 return r;
1453 }
1454
1455 #ifdef HAVE_ACL
1456 static int access_check_var_log_journal(sd_journal *j) {
1457 _cleanup_strv_free_ char **g = NULL;
1458 bool have_access;
1459 int r;
1460
1461 assert(j);
1462
1463 have_access = in_group("systemd-journal") > 0;
1464
1465 if (!have_access) {
1466 /* Let's enumerate all groups from the default ACL of
1467 * the directory, which generally should allow access
1468 * to most journal files too */
1469 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1470 if (r < 0)
1471 return r;
1472 }
1473
1474 if (!have_access) {
1475
1476 if (strv_isempty(g))
1477 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1478 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1479 " turn off this notice.");
1480 else {
1481 _cleanup_free_ char *s = NULL;
1482
1483 r = strv_extend(&g, "systemd-journal");
1484 if (r < 0)
1485 return log_oom();
1486
1487 strv_sort(g);
1488 strv_uniq(g);
1489
1490 s = strv_join(g, "', '");
1491 if (!s)
1492 return log_oom();
1493
1494 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1495 " Users in the groups '%s' can see all messages.\n"
1496 " Pass -q to turn off this notice.", s);
1497 }
1498 }
1499
1500 return 0;
1501 }
1502 #endif
1503
1504 static int access_check(sd_journal *j) {
1505 Iterator it;
1506 void *code;
1507 int r = 0;
1508
1509 assert(j);
1510
1511 if (set_isempty(j->errors)) {
1512 if (hashmap_isempty(j->files))
1513 log_notice("No journal files were found.");
1514 return 0;
1515 }
1516
1517 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1518 #ifdef HAVE_ACL
1519 /* If /var/log/journal doesn't even exist,
1520 * unprivileged users have no access at all */
1521 if (access("/var/log/journal", F_OK) < 0 &&
1522 geteuid() != 0 &&
1523 in_group("systemd-journal") <= 0) {
1524 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1525 "enabled. Users in the 'systemd-journal' group may always access messages.");
1526 return -EACCES;
1527 }
1528
1529 /* If /var/log/journal exists, try to pring a nice
1530 notice if the user lacks access to it */
1531 if (!arg_quiet && geteuid() != 0) {
1532 r = access_check_var_log_journal(j);
1533 if (r < 0)
1534 return r;
1535 }
1536 #else
1537 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1538 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1539 "group may access messages.");
1540 return -EACCES;
1541 }
1542 #endif
1543
1544 if (hashmap_isempty(j->files)) {
1545 log_error("No journal files were opened due to insufficient permissions.");
1546 r = -EACCES;
1547 }
1548 }
1549
1550 SET_FOREACH(code, j->errors, it) {
1551 int err;
1552
1553 err = -PTR_TO_INT(code);
1554 assert(err > 0);
1555
1556 if (err != EACCES)
1557 log_warning("Error was encountered while opening journal files: %s",
1558 strerror(err));
1559 }
1560
1561 return r;
1562 }
1563
1564 int main(int argc, char *argv[]) {
1565 int r;
1566 _cleanup_journal_close_ sd_journal *j = NULL;
1567 bool need_seek = false;
1568 sd_id128_t previous_boot_id;
1569 bool previous_boot_id_valid = false, first_line = true;
1570 int n_shown = 0;
1571 bool ellipsized = false;
1572
1573 setlocale(LC_ALL, "");
1574 log_parse_environment();
1575 log_open();
1576
1577 r = parse_argv(argc, argv);
1578 if (r <= 0)
1579 goto finish;
1580
1581 signal(SIGWINCH, columns_lines_cache_reset);
1582
1583 if (arg_action == ACTION_NEW_ID128) {
1584 r = generate_new_id128();
1585 goto finish;
1586 }
1587
1588 if (arg_action == ACTION_SETUP_KEYS) {
1589 r = setup_keys();
1590 goto finish;
1591 }
1592
1593 if (arg_action == ACTION_UPDATE_CATALOG ||
1594 arg_action == ACTION_LIST_CATALOG ||
1595 arg_action == ACTION_DUMP_CATALOG) {
1596
1597 const char* database = CATALOG_DATABASE;
1598 _cleanup_free_ char *copy = NULL;
1599 if (arg_root) {
1600 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1601 if (!copy) {
1602 r = log_oom();
1603 goto finish;
1604 }
1605 path_kill_slashes(copy);
1606 database = copy;
1607 }
1608
1609 if (arg_action == ACTION_UPDATE_CATALOG) {
1610 r = catalog_update(database, arg_root, catalog_file_dirs);
1611 if (r < 0)
1612 log_error("Failed to list catalog: %s", strerror(-r));
1613 } else {
1614 bool oneline = arg_action == ACTION_LIST_CATALOG;
1615
1616 if (optind < argc)
1617 r = catalog_list_items(stdout, database,
1618 oneline, argv + optind);
1619 else
1620 r = catalog_list(stdout, database, oneline);
1621 if (r < 0)
1622 log_error("Failed to list catalog: %s", strerror(-r));
1623 }
1624
1625 goto finish;
1626 }
1627
1628 if (arg_directory)
1629 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1630 else if (arg_file)
1631 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1632 else if (arg_machine)
1633 r = sd_journal_open_container(&j, arg_machine, 0);
1634 else
1635 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1636 if (r < 0) {
1637 log_error("Failed to open %s: %s",
1638 arg_directory ? arg_directory : arg_file ? "files" : "journal",
1639 strerror(-r));
1640 return EXIT_FAILURE;
1641 }
1642
1643 r = access_check(j);
1644 if (r < 0)
1645 return EXIT_FAILURE;
1646
1647 if (arg_action == ACTION_VERIFY) {
1648 r = verify(j);
1649 goto finish;
1650 }
1651
1652 if (arg_action == ACTION_PRINT_HEADER) {
1653 journal_print_header(j);
1654 return EXIT_SUCCESS;
1655 }
1656
1657 if (arg_action == ACTION_DISK_USAGE) {
1658 uint64_t bytes = 0;
1659 char sbytes[FORMAT_BYTES_MAX];
1660
1661 r = sd_journal_get_usage(j, &bytes);
1662 if (r < 0)
1663 return EXIT_FAILURE;
1664
1665 printf("Journals take up %s on disk.\n",
1666 format_bytes(sbytes, sizeof(sbytes), bytes));
1667 return EXIT_SUCCESS;
1668 }
1669
1670 if (arg_action == ACTION_LIST_BOOTS) {
1671 r = list_boots(j);
1672 goto finish;
1673 }
1674
1675 /* add_boot() must be called first!
1676 * It may need to seek the journal to find parent boot IDs. */
1677 r = add_boot(j);
1678 if (r < 0)
1679 return EXIT_FAILURE;
1680
1681 r = add_dmesg(j);
1682 if (r < 0)
1683 return EXIT_FAILURE;
1684
1685 r = add_units(j);
1686 strv_free(arg_system_units);
1687 strv_free(arg_user_units);
1688
1689 if (r < 0) {
1690 log_error("Failed to add filter for units: %s", strerror(-r));
1691 return EXIT_FAILURE;
1692 }
1693
1694 r = add_priorities(j);
1695 if (r < 0) {
1696 log_error("Failed to add filter for priorities: %s", strerror(-r));
1697 return EXIT_FAILURE;
1698 }
1699
1700 r = add_matches(j, argv + optind);
1701 if (r < 0) {
1702 log_error("Failed to add filters: %s", strerror(-r));
1703 return EXIT_FAILURE;
1704 }
1705
1706 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1707 _cleanup_free_ char *filter;
1708
1709 filter = journal_make_match_string(j);
1710 log_debug("Journal filter: %s", filter);
1711 }
1712
1713 if (arg_field) {
1714 const void *data;
1715 size_t size;
1716
1717 r = sd_journal_set_data_threshold(j, 0);
1718 if (r < 0) {
1719 log_error("Failed to unset data size threshold");
1720 return EXIT_FAILURE;
1721 }
1722
1723 r = sd_journal_query_unique(j, arg_field);
1724 if (r < 0) {
1725 log_error("Failed to query unique data objects: %s", strerror(-r));
1726 return EXIT_FAILURE;
1727 }
1728
1729 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1730 const void *eq;
1731
1732 if (arg_lines >= 0 && n_shown >= arg_lines)
1733 break;
1734
1735 eq = memchr(data, '=', size);
1736 if (eq)
1737 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1738 else
1739 printf("%.*s\n", (int) size, (const char*) data);
1740
1741 n_shown ++;
1742 }
1743
1744 return EXIT_SUCCESS;
1745 }
1746
1747 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1748 if (arg_follow) {
1749 r = sd_journal_get_fd(j);
1750 if (r < 0)
1751 return EXIT_FAILURE;
1752 }
1753
1754 if (arg_cursor || arg_after_cursor) {
1755 r = sd_journal_seek_cursor(j, arg_cursor ? arg_cursor : arg_after_cursor);
1756 if (r < 0) {
1757 log_error("Failed to seek to cursor: %s", strerror(-r));
1758 return EXIT_FAILURE;
1759 }
1760 if (!arg_reverse)
1761 r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1762 else
1763 r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1764
1765 if (arg_after_cursor && r < 2 && !arg_follow)
1766 /* We couldn't find the next entry after the cursor. */
1767 arg_lines = 0;
1768
1769 } else if (arg_since_set && !arg_reverse) {
1770 r = sd_journal_seek_realtime_usec(j, arg_since);
1771 if (r < 0) {
1772 log_error("Failed to seek to date: %s", strerror(-r));
1773 return EXIT_FAILURE;
1774 }
1775 r = sd_journal_next(j);
1776
1777 } else if (arg_until_set && arg_reverse) {
1778 r = sd_journal_seek_realtime_usec(j, arg_until);
1779 if (r < 0) {
1780 log_error("Failed to seek to date: %s", strerror(-r));
1781 return EXIT_FAILURE;
1782 }
1783 r = sd_journal_previous(j);
1784
1785 } else if (arg_lines >= 0) {
1786 r = sd_journal_seek_tail(j);
1787 if (r < 0) {
1788 log_error("Failed to seek to tail: %s", strerror(-r));
1789 return EXIT_FAILURE;
1790 }
1791
1792 r = sd_journal_previous_skip(j, arg_lines);
1793
1794 } else if (arg_reverse) {
1795 r = sd_journal_seek_tail(j);
1796 if (r < 0) {
1797 log_error("Failed to seek to tail: %s", strerror(-r));
1798 return EXIT_FAILURE;
1799 }
1800
1801 r = sd_journal_previous(j);
1802
1803 } else {
1804 r = sd_journal_seek_head(j);
1805 if (r < 0) {
1806 log_error("Failed to seek to head: %s", strerror(-r));
1807 return EXIT_FAILURE;
1808 }
1809
1810 r = sd_journal_next(j);
1811 }
1812
1813 if (r < 0) {
1814 log_error("Failed to iterate through journal: %s", strerror(-r));
1815 return EXIT_FAILURE;
1816 }
1817
1818 if (!arg_follow)
1819 pager_open_if_enabled();
1820
1821 if (!arg_quiet) {
1822 usec_t start, end;
1823 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1824
1825 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1826 if (r < 0) {
1827 log_error("Failed to get cutoff: %s", strerror(-r));
1828 goto finish;
1829 }
1830
1831 if (r > 0) {
1832 if (arg_follow)
1833 printf("-- Logs begin at %s. --\n",
1834 format_timestamp(start_buf, sizeof(start_buf), start));
1835 else
1836 printf("-- Logs begin at %s, end at %s. --\n",
1837 format_timestamp(start_buf, sizeof(start_buf), start),
1838 format_timestamp(end_buf, sizeof(end_buf), end));
1839 }
1840 }
1841
1842 for (;;) {
1843 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1844 int flags;
1845
1846 if (need_seek) {
1847 if (!arg_reverse)
1848 r = sd_journal_next(j);
1849 else
1850 r = sd_journal_previous(j);
1851 if (r < 0) {
1852 log_error("Failed to iterate through journal: %s", strerror(-r));
1853 goto finish;
1854 }
1855 if (r == 0)
1856 break;
1857 }
1858
1859 if (arg_until_set && !arg_reverse) {
1860 usec_t usec;
1861
1862 r = sd_journal_get_realtime_usec(j, &usec);
1863 if (r < 0) {
1864 log_error("Failed to determine timestamp: %s", strerror(-r));
1865 goto finish;
1866 }
1867 if (usec > arg_until)
1868 goto finish;
1869 }
1870
1871 if (arg_since_set && arg_reverse) {
1872 usec_t usec;
1873
1874 r = sd_journal_get_realtime_usec(j, &usec);
1875 if (r < 0) {
1876 log_error("Failed to determine timestamp: %s", strerror(-r));
1877 goto finish;
1878 }
1879 if (usec < arg_since)
1880 goto finish;
1881 }
1882
1883 if (!arg_merge) {
1884 sd_id128_t boot_id;
1885
1886 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1887 if (r >= 0) {
1888 if (previous_boot_id_valid &&
1889 !sd_id128_equal(boot_id, previous_boot_id))
1890 printf("%s-- Reboot --%s\n",
1891 ansi_highlight(), ansi_highlight_off());
1892
1893 previous_boot_id = boot_id;
1894 previous_boot_id_valid = true;
1895 }
1896 }
1897
1898 flags =
1899 arg_all * OUTPUT_SHOW_ALL |
1900 arg_full * OUTPUT_FULL_WIDTH |
1901 on_tty() * OUTPUT_COLOR |
1902 arg_catalog * OUTPUT_CATALOG;
1903
1904 r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
1905 need_seek = true;
1906 if (r == -EADDRNOTAVAIL)
1907 break;
1908 else if (r < 0 || ferror(stdout))
1909 goto finish;
1910
1911 n_shown++;
1912 }
1913
1914 if (!arg_follow) {
1915 if (arg_show_cursor) {
1916 _cleanup_free_ char *cursor = NULL;
1917
1918 r = sd_journal_get_cursor(j, &cursor);
1919 if (r < 0 && r != -EADDRNOTAVAIL)
1920 log_error("Failed to get cursor: %s", strerror(-r));
1921 else if (r >= 0)
1922 printf("-- cursor: %s\n", cursor);
1923 }
1924
1925 break;
1926 }
1927
1928 r = sd_journal_wait(j, (uint64_t) -1);
1929 if (r < 0) {
1930 log_error("Couldn't wait for journal event: %s", strerror(-r));
1931 goto finish;
1932 }
1933
1934 first_line = false;
1935 }
1936
1937 finish:
1938 pager_close();
1939
1940 strv_free(arg_file);
1941
1942 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1943 }