]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl.c
Always check asprintf return code
[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 the system journal\n"
171 " --user Show 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 bool have_term = false;
703
704 assert(j);
705
706 STRV_FOREACH(i, args) {
707 int r;
708
709 if (streq(*i, "+")) {
710 if (!have_term)
711 break;
712 r = sd_journal_add_disjunction(j);
713 have_term = false;
714
715 } else if (path_is_absolute(*i)) {
716 _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
717 const char *path;
718 _cleanup_free_ char *interpreter = NULL;
719 struct stat st;
720
721 p = canonicalize_file_name(*i);
722 path = p ? p : *i;
723
724 if (stat(path, &st) < 0) {
725 log_error("Couldn't stat file: %m");
726 return -errno;
727 }
728
729 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
730 if (executable_is_script(path, &interpreter) > 0) {
731 _cleanup_free_ char *comm;
732
733 comm = strndup(basename(path), 15);
734 if (!comm)
735 return log_oom();
736
737 t = strappend("_COMM=", comm);
738
739 /* Append _EXE only if the interpreter is not a link.
740 Otherwise, it might be outdated often. */
741 if (lstat(interpreter, &st) == 0 &&
742 !S_ISLNK(st.st_mode)) {
743 t2 = strappend("_EXE=", interpreter);
744 if (!t2)
745 return log_oom();
746 }
747 } else
748 t = strappend("_EXE=", path);
749 } else if (S_ISCHR(st.st_mode)) {
750 if (asprintf(&t, "_KERNEL_DEVICE=c%u:%u",
751 major(st.st_rdev),
752 minor(st.st_rdev)) < 0)
753 return -ENOMEM;
754 } else if (S_ISBLK(st.st_mode)) {
755 if (asprintf(&t, "_KERNEL_DEVICE=b%u:%u",
756 major(st.st_rdev),
757 minor(st.st_rdev)) < 0)
758 return -ENOMEM;
759 } else {
760 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
761 return -EINVAL;
762 }
763
764 if (!t)
765 return log_oom();
766
767 r = sd_journal_add_match(j, t, 0);
768 if (t2)
769 r = sd_journal_add_match(j, t2, 0);
770 have_term = true;
771
772 } else {
773 r = sd_journal_add_match(j, *i, 0);
774 have_term = true;
775 }
776
777 if (r < 0) {
778 log_error("Failed to add match '%s': %s", *i, strerror(-r));
779 return r;
780 }
781 }
782
783 if (!strv_isempty(args) && !have_term) {
784 log_error("\"+\" can only be used between terms");
785 return -EINVAL;
786 }
787
788 return 0;
789 }
790
791 static int boot_id_cmp(const void *a, const void *b) {
792 uint64_t _a, _b;
793
794 _a = ((const boot_id_t *)a)->first;
795 _b = ((const boot_id_t *)b)->first;
796
797 return _a < _b ? -1 : (_a > _b ? 1 : 0);
798 }
799
800 static int list_boots(sd_journal *j) {
801 int r;
802 const void *data;
803 unsigned int count = 0;
804 int w, i;
805 size_t length, allocated = 0;
806 boot_id_t *id;
807 _cleanup_free_ boot_id_t *all_ids = NULL;
808
809 r = sd_journal_query_unique(j, "_BOOT_ID");
810 if (r < 0)
811 return r;
812
813 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
814 if (length < strlen("_BOOT_ID="))
815 continue;
816
817 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
818 return log_oom();
819
820 id = &all_ids[count];
821
822 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
823 if (r < 0)
824 continue;
825
826 r = sd_journal_add_match(j, data, length);
827 if (r < 0)
828 return r;
829
830 r = sd_journal_seek_head(j);
831 if (r < 0)
832 return r;
833
834 r = sd_journal_next(j);
835 if (r < 0)
836 return r;
837 else if (r == 0)
838 goto flush;
839
840 r = sd_journal_get_realtime_usec(j, &id->first);
841 if (r < 0)
842 return r;
843
844 r = sd_journal_seek_tail(j);
845 if (r < 0)
846 return r;
847
848 r = sd_journal_previous(j);
849 if (r < 0)
850 return r;
851 else if (r == 0)
852 goto flush;
853
854 r = sd_journal_get_realtime_usec(j, &id->last);
855 if (r < 0)
856 return r;
857
858 count++;
859 flush:
860 sd_journal_flush_matches(j);
861 }
862
863 qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
864
865 /* numbers are one less, but we need an extra char for the sign */
866 w = DECIMAL_STR_WIDTH(count - 1) + 1;
867
868 for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
869 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
870
871 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
872 w, i - count + 1,
873 SD_ID128_FORMAT_VAL(id->id),
874 format_timestamp(a, sizeof(a), id->first),
875 format_timestamp(b, sizeof(b), id->last));
876 }
877
878 return 0;
879 }
880
881 static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
882 int r;
883 const void *data;
884 unsigned int count = 0;
885 size_t length, allocated = 0;
886 boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
887 _cleanup_free_ boot_id_t *all_ids = NULL;
888
889 assert(j);
890 assert(boot_id);
891
892 r = sd_journal_query_unique(j, "_BOOT_ID");
893 if (r < 0)
894 return r;
895
896 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
897 if (length < strlen("_BOOT_ID="))
898 continue;
899
900 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
901 return log_oom();
902
903 id = &all_ids[count];
904
905 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
906 if (r < 0)
907 continue;
908
909 r = sd_journal_add_match(j, data, length);
910 if (r < 0)
911 return r;
912
913 r = sd_journal_seek_head(j);
914 if (r < 0)
915 return r;
916
917 r = sd_journal_next(j);
918 if (r < 0)
919 return r;
920 else if (r == 0)
921 goto flush;
922
923 r = sd_journal_get_realtime_usec(j, &id->first);
924 if (r < 0)
925 return r;
926
927 if (sd_id128_equal(id->id, *boot_id))
928 ref_boot_id = *id;
929
930 count++;
931 flush:
932 sd_journal_flush_matches(j);
933 }
934
935 qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
936
937 if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
938 if (relative > (int) count || relative <= -(int)count)
939 return -EADDRNOTAVAIL;
940
941 *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
942 } else {
943 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
944
945 if (!id ||
946 relative <= 0 ? (id - all_ids) + relative < 0 :
947 (id - all_ids) + relative >= (int) count)
948 return -EADDRNOTAVAIL;
949
950 *boot_id = (id + relative)->id;
951 }
952
953 return 0;
954 }
955
956 static int add_boot(sd_journal *j) {
957 char match[9+32+1] = "_BOOT_ID=";
958 int r;
959
960 assert(j);
961
962 if (!arg_boot)
963 return 0;
964
965 if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
966 return add_match_this_boot(j, arg_machine);
967
968 r = get_relative_boot_id(j, &arg_boot_id, arg_boot_offset);
969 if (r < 0) {
970 if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
971 log_error("Failed to look up boot %+i: %s", arg_boot_offset, strerror(-r));
972 else
973 log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
974 SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, strerror(-r));
975 return r;
976 }
977
978 sd_id128_to_string(arg_boot_id, match + 9);
979
980 r = sd_journal_add_match(j, match, sizeof(match) - 1);
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 add_dmesg(sd_journal *j) {
994 int r;
995 assert(j);
996
997 if (!arg_dmesg)
998 return 0;
999
1000 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1001 if (r < 0) {
1002 log_error("Failed to add match: %s", strerror(-r));
1003 return r;
1004 }
1005
1006 r = sd_journal_add_conjunction(j);
1007 if (r < 0)
1008 return r;
1009
1010 return 0;
1011 }
1012
1013 static int get_possible_units(sd_journal *j,
1014 const char *fields,
1015 char **patterns,
1016 Set **units) {
1017 _cleanup_set_free_free_ Set *found;
1018 const char *field;
1019 int r;
1020
1021 found = set_new(string_hash_func, string_compare_func);
1022 if (!found)
1023 return log_oom();
1024
1025 NULSTR_FOREACH(field, fields) {
1026 const void *data;
1027 size_t size;
1028
1029 r = sd_journal_query_unique(j, field);
1030 if (r < 0)
1031 return r;
1032
1033 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1034 char **pattern, *eq;
1035 size_t prefix;
1036 _cleanup_free_ char *u = NULL;
1037
1038 eq = memchr(data, '=', size);
1039 if (eq)
1040 prefix = eq - (char*) data + 1;
1041 else
1042 prefix = 0;
1043
1044 u = strndup((char*) data + prefix, size - prefix);
1045 if (!u)
1046 return log_oom();
1047
1048 STRV_FOREACH(pattern, patterns)
1049 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1050 log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1051
1052 r = set_consume(found, u);
1053 u = NULL;
1054 if (r < 0 && r != -EEXIST)
1055 return r;
1056
1057 break;
1058 }
1059 }
1060 }
1061
1062 *units = found;
1063 found = NULL;
1064 return 0;
1065 }
1066
1067 /* This list is supposed to return the superset of unit names
1068 * possibly matched by rules added with add_matches_for_unit... */
1069 #define SYSTEM_UNITS \
1070 "_SYSTEMD_UNIT\0" \
1071 "COREDUMP_UNIT\0" \
1072 "UNIT\0" \
1073 "OBJECT_SYSTEMD_UNIT\0" \
1074 "_SYSTEMD_SLICE\0"
1075
1076 /* ... and add_matches_for_user_unit */
1077 #define USER_UNITS \
1078 "_SYSTEMD_USER_UNIT\0" \
1079 "USER_UNIT\0" \
1080 "COREDUMP_USER_UNIT\0" \
1081 "OBJECT_SYSTEMD_USER_UNIT\0"
1082
1083 static int add_units(sd_journal *j) {
1084 _cleanup_strv_free_ char **patterns = NULL;
1085 int r, count = 0;
1086 char **i;
1087
1088 assert(j);
1089
1090 STRV_FOREACH(i, arg_system_units) {
1091 _cleanup_free_ char *u = NULL;
1092
1093 u = unit_name_mangle(*i, MANGLE_GLOB);
1094 if (!u)
1095 return log_oom();
1096
1097 if (string_is_glob(u)) {
1098 r = strv_push(&patterns, u);
1099 if (r < 0)
1100 return r;
1101 u = NULL;
1102 } else {
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 if (!strv_isempty(patterns)) {
1114 _cleanup_set_free_free_ Set *units = NULL;
1115 Iterator it;
1116 char *u;
1117
1118 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1119 if (r < 0)
1120 return r;
1121
1122 SET_FOREACH(u, units, it) {
1123 r = add_matches_for_unit(j, u);
1124 if (r < 0)
1125 return r;
1126 r = sd_journal_add_disjunction(j);
1127 if (r < 0)
1128 return r;
1129 count ++;
1130 }
1131 }
1132
1133 strv_free(patterns);
1134 patterns = NULL;
1135
1136 STRV_FOREACH(i, arg_user_units) {
1137 _cleanup_free_ char *u = NULL;
1138
1139 u = unit_name_mangle(*i, MANGLE_GLOB);
1140 if (!u)
1141 return log_oom();
1142
1143 if (string_is_glob(u)) {
1144 r = strv_push(&patterns, u);
1145 if (r < 0)
1146 return r;
1147 u = NULL;
1148 } else {
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 if (!strv_isempty(patterns)) {
1160 _cleanup_set_free_free_ Set *units = NULL;
1161 Iterator it;
1162 char *u;
1163
1164 r = get_possible_units(j, USER_UNITS, patterns, &units);
1165 if (r < 0)
1166 return r;
1167
1168 SET_FOREACH(u, units, it) {
1169 r = add_matches_for_user_unit(j, u, getuid());
1170 if (r < 0)
1171 return r;
1172 r = sd_journal_add_disjunction(j);
1173 if (r < 0)
1174 return r;
1175 count ++;
1176 }
1177 }
1178
1179 /* Complain if the user request matches but nothing whatsoever was
1180 * found, since otherwise everything would be matched. */
1181 if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1182 return -ENODATA;
1183
1184 r = sd_journal_add_conjunction(j);
1185 if (r < 0)
1186 return r;
1187
1188 return 0;
1189 }
1190
1191 static int add_priorities(sd_journal *j) {
1192 char match[] = "PRIORITY=0";
1193 int i, r;
1194 assert(j);
1195
1196 if (arg_priorities == 0xFF)
1197 return 0;
1198
1199 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1200 if (arg_priorities & (1 << i)) {
1201 match[sizeof(match)-2] = '0' + i;
1202
1203 r = sd_journal_add_match(j, match, strlen(match));
1204 if (r < 0) {
1205 log_error("Failed to add match: %s", strerror(-r));
1206 return r;
1207 }
1208 }
1209
1210 r = sd_journal_add_conjunction(j);
1211 if (r < 0)
1212 return r;
1213
1214 return 0;
1215 }
1216
1217 static int setup_keys(void) {
1218 #ifdef HAVE_GCRYPT
1219 size_t mpk_size, seed_size, state_size, i;
1220 uint8_t *mpk, *seed, *state;
1221 ssize_t l;
1222 int fd = -1, r, attr = 0;
1223 sd_id128_t machine, boot;
1224 char *p = NULL, *k = NULL;
1225 struct FSSHeader h;
1226 uint64_t n;
1227 struct stat st;
1228
1229 r = stat("/var/log/journal", &st);
1230 if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
1231 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
1232 return -errno;
1233 }
1234
1235 if (r < 0 || !S_ISDIR(st.st_mode)) {
1236 log_error("%s is not a directory, must be using persistent logging for FSS.",
1237 "/var/log/journal");
1238 return r < 0 ? -errno : -ENOTDIR;
1239 }
1240
1241 r = sd_id128_get_machine(&machine);
1242 if (r < 0) {
1243 log_error("Failed to get machine ID: %s", strerror(-r));
1244 return r;
1245 }
1246
1247 r = sd_id128_get_boot(&boot);
1248 if (r < 0) {
1249 log_error("Failed to get boot ID: %s", strerror(-r));
1250 return r;
1251 }
1252
1253 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1254 SD_ID128_FORMAT_VAL(machine)) < 0)
1255 return log_oom();
1256
1257 if (access(p, F_OK) >= 0) {
1258 if (arg_force) {
1259 r = unlink(p);
1260 if (r < 0) {
1261 log_error("unlink(\"%s\") failed: %m", p);
1262 r = -errno;
1263 goto finish;
1264 }
1265 } else {
1266 log_error("Sealing key file %s exists already. (--force to recreate)", p);
1267 r = -EEXIST;
1268 goto finish;
1269 }
1270 }
1271
1272 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1273 SD_ID128_FORMAT_VAL(machine)) < 0) {
1274 r = log_oom();
1275 goto finish;
1276 }
1277
1278 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1279 mpk = alloca(mpk_size);
1280
1281 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1282 seed = alloca(seed_size);
1283
1284 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1285 state = alloca(state_size);
1286
1287 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1288 if (fd < 0) {
1289 log_error("Failed to open /dev/random: %m");
1290 r = -errno;
1291 goto finish;
1292 }
1293
1294 log_info("Generating seed...");
1295 l = loop_read(fd, seed, seed_size, true);
1296 if (l < 0 || (size_t) l != seed_size) {
1297 log_error("Failed to read random seed: %s", strerror(EIO));
1298 r = -EIO;
1299 goto finish;
1300 }
1301
1302 log_info("Generating key pair...");
1303 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1304
1305 log_info("Generating sealing key...");
1306 FSPRG_GenState0(state, mpk, seed, seed_size);
1307
1308 assert(arg_interval > 0);
1309
1310 n = now(CLOCK_REALTIME);
1311 n /= arg_interval;
1312
1313 safe_close(fd);
1314 fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1315 if (fd < 0) {
1316 log_error("Failed to open %s: %m", k);
1317 r = -errno;
1318 goto finish;
1319 }
1320
1321 /* Enable secure remove, exclusion from dump, synchronous
1322 * writing and in-place updating */
1323 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
1324 log_warning("FS_IOC_GETFLAGS failed: %m");
1325
1326 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1327
1328 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1329 log_warning("FS_IOC_SETFLAGS failed: %m");
1330
1331 zero(h);
1332 memcpy(h.signature, "KSHHRHLP", 8);
1333 h.machine_id = machine;
1334 h.boot_id = boot;
1335 h.header_size = htole64(sizeof(h));
1336 h.start_usec = htole64(n * arg_interval);
1337 h.interval_usec = htole64(arg_interval);
1338 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1339 h.fsprg_state_size = htole64(state_size);
1340
1341 l = loop_write(fd, &h, sizeof(h), false);
1342 if (l < 0 || (size_t) l != sizeof(h)) {
1343 log_error("Failed to write header: %s", strerror(EIO));
1344 r = -EIO;
1345 goto finish;
1346 }
1347
1348 l = loop_write(fd, state, state_size, false);
1349 if (l < 0 || (size_t) l != state_size) {
1350 log_error("Failed to write state: %s", strerror(EIO));
1351 r = -EIO;
1352 goto finish;
1353 }
1354
1355 if (link(k, p) < 0) {
1356 log_error("Failed to link file: %m");
1357 r = -errno;
1358 goto finish;
1359 }
1360
1361 if (on_tty()) {
1362 fprintf(stderr,
1363 "\n"
1364 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
1365 "the following local file. This key file is automatically updated when the\n"
1366 "sealing key is advanced. It should not be used on multiple hosts.\n"
1367 "\n"
1368 "\t%s\n"
1369 "\n"
1370 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
1371 "at a safe location and should not be saved locally on disk.\n"
1372 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
1373 fflush(stderr);
1374 }
1375 for (i = 0; i < seed_size; i++) {
1376 if (i > 0 && i % 3 == 0)
1377 putchar('-');
1378 printf("%02x", ((uint8_t*) seed)[i]);
1379 }
1380
1381 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1382
1383 if (on_tty()) {
1384 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1385
1386 fprintf(stderr,
1387 ANSI_HIGHLIGHT_OFF "\n"
1388 "The sealing key is automatically changed every %s.\n",
1389 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1390
1391 hn = gethostname_malloc();
1392
1393 if (hn) {
1394 hostname_cleanup(hn, false);
1395 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1396 } else
1397 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1398
1399 #ifdef HAVE_QRENCODE
1400 /* If this is not an UTF-8 system don't print any QR codes */
1401 if (is_locale_utf8()) {
1402 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1403 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1404 }
1405 #endif
1406 free(hn);
1407 }
1408
1409 r = 0;
1410
1411 finish:
1412 safe_close(fd);
1413
1414 if (k) {
1415 unlink(k);
1416 free(k);
1417 }
1418
1419 free(p);
1420
1421 return r;
1422 #else
1423 log_error("Forward-secure sealing not available.");
1424 return -ENOTSUP;
1425 #endif
1426 }
1427
1428 static int verify(sd_journal *j) {
1429 int r = 0;
1430 Iterator i;
1431 JournalFile *f;
1432
1433 assert(j);
1434
1435 log_show_color(true);
1436
1437 HASHMAP_FOREACH(f, j->files, i) {
1438 int k;
1439 usec_t first, validated, last;
1440
1441 #ifdef HAVE_GCRYPT
1442 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1443 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1444 #endif
1445
1446 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1447 if (k == -EINVAL) {
1448 /* If the key was invalid give up right-away. */
1449 return k;
1450 } else if (k < 0) {
1451 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1452 r = k;
1453 } else {
1454 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1455 log_info("PASS: %s", f->path);
1456
1457 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1458 if (validated > 0) {
1459 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1460 format_timestamp(a, sizeof(a), first),
1461 format_timestamp(b, sizeof(b), validated),
1462 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1463 } else if (last > 0)
1464 log_info("=> No sealing yet, %s of entries not sealed.",
1465 format_timespan(c, sizeof(c), last - first, 0));
1466 else
1467 log_info("=> No sealing yet, no entries in file.");
1468 }
1469 }
1470 }
1471
1472 return r;
1473 }
1474
1475 #ifdef HAVE_ACL
1476 static int access_check_var_log_journal(sd_journal *j) {
1477 _cleanup_strv_free_ char **g = NULL;
1478 bool have_access;
1479 int r;
1480
1481 assert(j);
1482
1483 have_access = in_group("systemd-journal") > 0;
1484
1485 if (!have_access) {
1486 /* Let's enumerate all groups from the default ACL of
1487 * the directory, which generally should allow access
1488 * to most journal files too */
1489 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1490 if (r < 0)
1491 return r;
1492 }
1493
1494 if (!have_access) {
1495
1496 if (strv_isempty(g))
1497 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1498 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1499 " turn off this notice.");
1500 else {
1501 _cleanup_free_ char *s = NULL;
1502
1503 r = strv_extend(&g, "systemd-journal");
1504 if (r < 0)
1505 return log_oom();
1506
1507 strv_sort(g);
1508 strv_uniq(g);
1509
1510 s = strv_join(g, "', '");
1511 if (!s)
1512 return log_oom();
1513
1514 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1515 " Users in the groups '%s' can see all messages.\n"
1516 " Pass -q to turn off this notice.", s);
1517 }
1518 }
1519
1520 return 0;
1521 }
1522 #endif
1523
1524 static int access_check(sd_journal *j) {
1525 Iterator it;
1526 void *code;
1527 int r = 0;
1528
1529 assert(j);
1530
1531 if (set_isempty(j->errors)) {
1532 if (hashmap_isempty(j->files))
1533 log_notice("No journal files were found.");
1534 return 0;
1535 }
1536
1537 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1538 #ifdef HAVE_ACL
1539 /* If /var/log/journal doesn't even exist,
1540 * unprivileged users have no access at all */
1541 if (access("/var/log/journal", F_OK) < 0 &&
1542 geteuid() != 0 &&
1543 in_group("systemd-journal") <= 0) {
1544 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1545 "enabled. Users in the 'systemd-journal' group may always access messages.");
1546 return -EACCES;
1547 }
1548
1549 /* If /var/log/journal exists, try to pring a nice
1550 notice if the user lacks access to it */
1551 if (!arg_quiet && geteuid() != 0) {
1552 r = access_check_var_log_journal(j);
1553 if (r < 0)
1554 return r;
1555 }
1556 #else
1557 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1558 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1559 "group may access messages.");
1560 return -EACCES;
1561 }
1562 #endif
1563
1564 if (hashmap_isempty(j->files)) {
1565 log_error("No journal files were opened due to insufficient permissions.");
1566 r = -EACCES;
1567 }
1568 }
1569
1570 SET_FOREACH(code, j->errors, it) {
1571 int err;
1572
1573 err = -PTR_TO_INT(code);
1574 assert(err > 0);
1575
1576 if (err != EACCES)
1577 log_warning("Error was encountered while opening journal files: %s",
1578 strerror(err));
1579 }
1580
1581 return r;
1582 }
1583
1584 int main(int argc, char *argv[]) {
1585 int r;
1586 _cleanup_journal_close_ sd_journal *j = NULL;
1587 bool need_seek = false;
1588 sd_id128_t previous_boot_id;
1589 bool previous_boot_id_valid = false, first_line = true;
1590 int n_shown = 0;
1591 bool ellipsized = false;
1592
1593 setlocale(LC_ALL, "");
1594 log_parse_environment();
1595 log_open();
1596
1597 r = parse_argv(argc, argv);
1598 if (r <= 0)
1599 goto finish;
1600
1601 signal(SIGWINCH, columns_lines_cache_reset);
1602
1603 if (arg_action == ACTION_NEW_ID128) {
1604 r = generate_new_id128();
1605 goto finish;
1606 }
1607
1608 if (arg_action == ACTION_SETUP_KEYS) {
1609 r = setup_keys();
1610 goto finish;
1611 }
1612
1613 if (arg_action == ACTION_UPDATE_CATALOG ||
1614 arg_action == ACTION_LIST_CATALOG ||
1615 arg_action == ACTION_DUMP_CATALOG) {
1616
1617 const char* database = CATALOG_DATABASE;
1618 _cleanup_free_ char *copy = NULL;
1619 if (arg_root) {
1620 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1621 if (!copy) {
1622 r = log_oom();
1623 goto finish;
1624 }
1625 path_kill_slashes(copy);
1626 database = copy;
1627 }
1628
1629 if (arg_action == ACTION_UPDATE_CATALOG) {
1630 r = catalog_update(database, arg_root, catalog_file_dirs);
1631 if (r < 0)
1632 log_error("Failed to list catalog: %s", strerror(-r));
1633 } else {
1634 bool oneline = arg_action == ACTION_LIST_CATALOG;
1635
1636 if (optind < argc)
1637 r = catalog_list_items(stdout, database,
1638 oneline, argv + optind);
1639 else
1640 r = catalog_list(stdout, database, oneline);
1641 if (r < 0)
1642 log_error("Failed to list catalog: %s", strerror(-r));
1643 }
1644
1645 goto finish;
1646 }
1647
1648 if (arg_directory)
1649 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1650 else if (arg_file)
1651 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1652 else if (arg_machine)
1653 r = sd_journal_open_container(&j, arg_machine, 0);
1654 else
1655 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1656 if (r < 0) {
1657 log_error("Failed to open %s: %s",
1658 arg_directory ? arg_directory : arg_file ? "files" : "journal",
1659 strerror(-r));
1660 return EXIT_FAILURE;
1661 }
1662
1663 r = access_check(j);
1664 if (r < 0)
1665 return EXIT_FAILURE;
1666
1667 if (arg_action == ACTION_VERIFY) {
1668 r = verify(j);
1669 goto finish;
1670 }
1671
1672 if (arg_action == ACTION_PRINT_HEADER) {
1673 journal_print_header(j);
1674 return EXIT_SUCCESS;
1675 }
1676
1677 if (arg_action == ACTION_DISK_USAGE) {
1678 uint64_t bytes = 0;
1679 char sbytes[FORMAT_BYTES_MAX];
1680
1681 r = sd_journal_get_usage(j, &bytes);
1682 if (r < 0)
1683 return EXIT_FAILURE;
1684
1685 printf("Journals take up %s on disk.\n",
1686 format_bytes(sbytes, sizeof(sbytes), bytes));
1687 return EXIT_SUCCESS;
1688 }
1689
1690 if (arg_action == ACTION_LIST_BOOTS) {
1691 r = list_boots(j);
1692 goto finish;
1693 }
1694
1695 /* add_boot() must be called first!
1696 * It may need to seek the journal to find parent boot IDs. */
1697 r = add_boot(j);
1698 if (r < 0)
1699 return EXIT_FAILURE;
1700
1701 r = add_dmesg(j);
1702 if (r < 0)
1703 return EXIT_FAILURE;
1704
1705 r = add_units(j);
1706 strv_free(arg_system_units);
1707 strv_free(arg_user_units);
1708
1709 if (r < 0) {
1710 log_error("Failed to add filter for units: %s", strerror(-r));
1711 return EXIT_FAILURE;
1712 }
1713
1714 r = add_priorities(j);
1715 if (r < 0) {
1716 log_error("Failed to add filter for priorities: %s", strerror(-r));
1717 return EXIT_FAILURE;
1718 }
1719
1720 r = add_matches(j, argv + optind);
1721 if (r < 0) {
1722 log_error("Failed to add filters: %s", strerror(-r));
1723 return EXIT_FAILURE;
1724 }
1725
1726 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1727 _cleanup_free_ char *filter;
1728
1729 filter = journal_make_match_string(j);
1730 log_debug("Journal filter: %s", filter);
1731 }
1732
1733 if (arg_field) {
1734 const void *data;
1735 size_t size;
1736
1737 r = sd_journal_set_data_threshold(j, 0);
1738 if (r < 0) {
1739 log_error("Failed to unset data size threshold");
1740 return EXIT_FAILURE;
1741 }
1742
1743 r = sd_journal_query_unique(j, arg_field);
1744 if (r < 0) {
1745 log_error("Failed to query unique data objects: %s", strerror(-r));
1746 return EXIT_FAILURE;
1747 }
1748
1749 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1750 const void *eq;
1751
1752 if (arg_lines >= 0 && n_shown >= arg_lines)
1753 break;
1754
1755 eq = memchr(data, '=', size);
1756 if (eq)
1757 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1758 else
1759 printf("%.*s\n", (int) size, (const char*) data);
1760
1761 n_shown ++;
1762 }
1763
1764 return EXIT_SUCCESS;
1765 }
1766
1767 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1768 if (arg_follow) {
1769 r = sd_journal_get_fd(j);
1770 if (r < 0)
1771 return EXIT_FAILURE;
1772 }
1773
1774 if (arg_cursor || arg_after_cursor) {
1775 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
1776 if (r < 0) {
1777 log_error("Failed to seek to cursor: %s", strerror(-r));
1778 return EXIT_FAILURE;
1779 }
1780 if (!arg_reverse)
1781 r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1782 else
1783 r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1784
1785 if (arg_after_cursor && r < 2 && !arg_follow)
1786 /* We couldn't find the next entry after the cursor. */
1787 arg_lines = 0;
1788
1789 } else if (arg_since_set && !arg_reverse) {
1790 r = sd_journal_seek_realtime_usec(j, arg_since);
1791 if (r < 0) {
1792 log_error("Failed to seek to date: %s", strerror(-r));
1793 return EXIT_FAILURE;
1794 }
1795 r = sd_journal_next(j);
1796
1797 } else if (arg_until_set && arg_reverse) {
1798 r = sd_journal_seek_realtime_usec(j, arg_until);
1799 if (r < 0) {
1800 log_error("Failed to seek to date: %s", strerror(-r));
1801 return EXIT_FAILURE;
1802 }
1803 r = sd_journal_previous(j);
1804
1805 } else if (arg_lines >= 0) {
1806 r = sd_journal_seek_tail(j);
1807 if (r < 0) {
1808 log_error("Failed to seek to tail: %s", strerror(-r));
1809 return EXIT_FAILURE;
1810 }
1811
1812 r = sd_journal_previous_skip(j, arg_lines);
1813
1814 } else if (arg_reverse) {
1815 r = sd_journal_seek_tail(j);
1816 if (r < 0) {
1817 log_error("Failed to seek to tail: %s", strerror(-r));
1818 return EXIT_FAILURE;
1819 }
1820
1821 r = sd_journal_previous(j);
1822
1823 } else {
1824 r = sd_journal_seek_head(j);
1825 if (r < 0) {
1826 log_error("Failed to seek to head: %s", strerror(-r));
1827 return EXIT_FAILURE;
1828 }
1829
1830 r = sd_journal_next(j);
1831 }
1832
1833 if (r < 0) {
1834 log_error("Failed to iterate through journal: %s", strerror(-r));
1835 return EXIT_FAILURE;
1836 }
1837
1838 if (!arg_follow)
1839 pager_open_if_enabled();
1840
1841 if (!arg_quiet) {
1842 usec_t start, end;
1843 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1844
1845 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1846 if (r < 0) {
1847 log_error("Failed to get cutoff: %s", strerror(-r));
1848 goto finish;
1849 }
1850
1851 if (r > 0) {
1852 if (arg_follow)
1853 printf("-- Logs begin at %s. --\n",
1854 format_timestamp(start_buf, sizeof(start_buf), start));
1855 else
1856 printf("-- Logs begin at %s, end at %s. --\n",
1857 format_timestamp(start_buf, sizeof(start_buf), start),
1858 format_timestamp(end_buf, sizeof(end_buf), end));
1859 }
1860 }
1861
1862 for (;;) {
1863 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1864 int flags;
1865
1866 if (need_seek) {
1867 if (!arg_reverse)
1868 r = sd_journal_next(j);
1869 else
1870 r = sd_journal_previous(j);
1871 if (r < 0) {
1872 log_error("Failed to iterate through journal: %s", strerror(-r));
1873 goto finish;
1874 }
1875 if (r == 0)
1876 break;
1877 }
1878
1879 if (arg_until_set && !arg_reverse) {
1880 usec_t usec;
1881
1882 r = sd_journal_get_realtime_usec(j, &usec);
1883 if (r < 0) {
1884 log_error("Failed to determine timestamp: %s", strerror(-r));
1885 goto finish;
1886 }
1887 if (usec > arg_until)
1888 goto finish;
1889 }
1890
1891 if (arg_since_set && arg_reverse) {
1892 usec_t usec;
1893
1894 r = sd_journal_get_realtime_usec(j, &usec);
1895 if (r < 0) {
1896 log_error("Failed to determine timestamp: %s", strerror(-r));
1897 goto finish;
1898 }
1899 if (usec < arg_since)
1900 goto finish;
1901 }
1902
1903 if (!arg_merge) {
1904 sd_id128_t boot_id;
1905
1906 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1907 if (r >= 0) {
1908 if (previous_boot_id_valid &&
1909 !sd_id128_equal(boot_id, previous_boot_id))
1910 printf("%s-- Reboot --%s\n",
1911 ansi_highlight(), ansi_highlight_off());
1912
1913 previous_boot_id = boot_id;
1914 previous_boot_id_valid = true;
1915 }
1916 }
1917
1918 flags =
1919 arg_all * OUTPUT_SHOW_ALL |
1920 arg_full * OUTPUT_FULL_WIDTH |
1921 on_tty() * OUTPUT_COLOR |
1922 arg_catalog * OUTPUT_CATALOG;
1923
1924 r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
1925 need_seek = true;
1926 if (r == -EADDRNOTAVAIL)
1927 break;
1928 else if (r < 0 || ferror(stdout))
1929 goto finish;
1930
1931 n_shown++;
1932 }
1933
1934 if (!arg_follow) {
1935 if (arg_show_cursor) {
1936 _cleanup_free_ char *cursor = NULL;
1937
1938 r = sd_journal_get_cursor(j, &cursor);
1939 if (r < 0 && r != -EADDRNOTAVAIL)
1940 log_error("Failed to get cursor: %s", strerror(-r));
1941 else if (r >= 0)
1942 printf("-- cursor: %s\n", cursor);
1943 }
1944
1945 break;
1946 }
1947
1948 r = sd_journal_wait(j, (uint64_t) -1);
1949 if (r < 0) {
1950 log_error("Couldn't wait for journal event: %s", strerror(-r));
1951 goto finish;
1952 }
1953
1954 first_line = false;
1955 }
1956
1957 finish:
1958 pager_close();
1959
1960 strv_free(arg_file);
1961
1962 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1963 }