1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
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.
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.
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/>.
35 #include <sys/ioctl.h>
43 #include "systemd/sd-journal.h"
46 #include "logs-show.h"
48 #include "path-util.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"
60 #include "unit-name.h"
63 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
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;
87 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
88 static bool arg_force = false;
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;
110 ACTION_UPDATE_CATALOG,
112 } arg_action = ACTION_SHOW;
114 typedef struct boot_id_t {
120 static void pager_open_if_enabled(void) {
125 pager_open(arg_pager_end);
128 static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) {
129 sd_id128_t id = SD_ID128_NULL;
132 if (strlen(x) >= 32) {
136 r = sd_id128_from_string(t, &id);
140 if (*x != '-' && *x != '+' && *x != 0)
144 r = safe_atoi(x, &off);
149 r = safe_atoi(x, &off);
163 static int help(void) {
165 pager_open_if_enabled();
167 printf("%s [OPTIONS...] [MATCHES...]\n\n"
168 "Query the journal.\n\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"
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"
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"
217 " --setup-keys Generate a new FSS key pair\n"
218 " --verify Verify journal file consistency\n"
220 , program_invocation_short_name);
225 static int parse_argv(int argc, char *argv[]) {
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' },
309 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xrM:", options, NULL)) >= 0) {
317 puts(PACKAGE_STRING);
318 puts(SYSTEMD_FEATURES);
326 arg_pager_end = true;
338 arg_output = output_mode_from_string(optarg);
339 if (arg_output < 0) {
340 log_error("Unknown output format '%s'.", optarg);
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)
367 r = safe_atoi(optarg, &arg_lines);
368 if (r < 0 || arg_lines < 0) {
369 log_error("Failed to parse lines '%s'", optarg);
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
383 safe_atoi(argv[optind], &n) >= 0 &&
399 arg_action = ACTION_NEW_ID128;
414 r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
416 log_error("Failed to parse boot descriptor '%s'", optarg);
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... */
428 parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset) >= 0)
435 arg_action = ACTION_LIST_BOOTS;
439 arg_boot = arg_dmesg = true;
443 arg_journal_type |= SD_JOURNAL_SYSTEM;
447 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
451 arg_machine = optarg;
455 arg_directory = optarg;
459 r = glob_extend(&arg_file, optarg);
461 log_error("Failed to add paths: %s", strerror(-r));
474 case ARG_AFTER_CURSOR:
475 arg_after_cursor = optarg;
478 case ARG_SHOW_CURSOR:
479 arg_show_cursor = true;
483 arg_action = ACTION_PRINT_HEADER;
487 arg_action = ACTION_VERIFY;
491 arg_action = ACTION_DISK_USAGE;
500 arg_action = ACTION_SETUP_KEYS;
505 arg_action = ACTION_VERIFY;
506 arg_verify_key = optarg;
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);
522 log_error("Forward-secure sealing not available.");
529 dots = strstr(optarg, "..");
535 a = strndup(optarg, dots - optarg);
539 from = log_level_from_string(a);
540 to = log_level_from_string(dots + 2);
543 if (from < 0 || to < 0) {
544 log_error("Failed to parse log level range %s", optarg);
551 for (i = from; i <= to; i++)
552 arg_priorities |= 1 << i;
554 for (i = to; i <= from; i++)
555 arg_priorities |= 1 << i;
561 p = log_level_from_string(optarg);
563 log_error("Unknown log level %s", optarg);
569 for (i = 0; i <= p; i++)
570 arg_priorities |= 1 << i;
577 r = parse_timestamp(optarg, &arg_since);
579 log_error("Failed to parse timestamp: %s", optarg);
582 arg_since_set = true;
586 r = parse_timestamp(optarg, &arg_until);
588 log_error("Failed to parse timestamp: %s", optarg);
591 arg_until_set = true;
595 r = strv_extend(&arg_system_units, optarg);
601 r = strv_extend(&arg_user_units, optarg);
614 case ARG_LIST_CATALOG:
615 arg_action = ACTION_LIST_CATALOG;
618 case ARG_DUMP_CATALOG:
619 arg_action = ACTION_DUMP_CATALOG;
622 case ARG_UPDATE_CATALOG:
623 arg_action = ACTION_UPDATE_CATALOG;
634 assert_not_reached("Unhandled option");
638 if (arg_follow && !arg_no_tail && arg_lines < 0)
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.");
646 if (arg_since_set && arg_until_set && arg_since > arg_until) {
647 log_error("--since= must be before --until=.");
651 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
652 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
656 if (arg_follow && arg_reverse) {
657 log_error("Please specify either --reverse= or --follow=, not both.");
661 if (arg_action != ACTION_SHOW && optind < argc) {
662 log_error("Extraneous arguments starting with '%s'", argv[optind]);
669 static int generate_new_id128(void) {
674 r = sd_id128_randomize(&id);
676 log_error("Failed to generate ID: %s", strerror(-r));
680 printf("As string:\n"
681 SD_ID128_FORMAT_STR "\n\n"
683 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\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);
692 printf("As Python constant:\n"
694 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
695 SD_ID128_FORMAT_VAL(id));
700 static int add_matches(sd_journal *j, char **args) {
702 bool have_term = false;
706 STRV_FOREACH(i, args) {
709 if (streq(*i, "+")) {
712 r = sd_journal_add_disjunction(j);
715 } else if (path_is_absolute(*i)) {
716 _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
718 _cleanup_free_ char *interpreter = NULL;
721 p = canonicalize_file_name(*i);
724 if (stat(path, &st) < 0) {
725 log_error("Couldn't stat file: %m");
729 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
730 if (executable_is_script(path, &interpreter) > 0) {
731 _cleanup_free_ char *comm;
733 comm = strndup(basename(path), 15);
737 t = strappend("_COMM=", comm);
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);
748 t = strappend("_EXE=", path);
749 } else if (S_ISCHR(st.st_mode)) {
750 if (asprintf(&t, "_KERNEL_DEVICE=c%u:%u",
752 minor(st.st_rdev)) < 0)
754 } else if (S_ISBLK(st.st_mode)) {
755 if (asprintf(&t, "_KERNEL_DEVICE=b%u:%u",
757 minor(st.st_rdev)) < 0)
760 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
767 r = sd_journal_add_match(j, t, 0);
769 r = sd_journal_add_match(j, t2, 0);
773 r = sd_journal_add_match(j, *i, 0);
778 log_error("Failed to add match '%s': %s", *i, strerror(-r));
783 if (!strv_isempty(args) && !have_term) {
784 log_error("\"+\" can only be used between terms");
791 static int boot_id_cmp(const void *a, const void *b) {
794 _a = ((const boot_id_t *)a)->first;
795 _b = ((const boot_id_t *)b)->first;
797 return _a < _b ? -1 : (_a > _b ? 1 : 0);
800 static int list_boots(sd_journal *j) {
803 unsigned int count = 0;
805 size_t length, allocated = 0;
807 _cleanup_free_ boot_id_t *all_ids = NULL;
809 r = sd_journal_query_unique(j, "_BOOT_ID");
813 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
814 if (length < strlen("_BOOT_ID="))
817 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
820 id = &all_ids[count];
822 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
826 r = sd_journal_add_match(j, data, length);
830 r = sd_journal_seek_head(j);
834 r = sd_journal_next(j);
840 r = sd_journal_get_realtime_usec(j, &id->first);
844 r = sd_journal_seek_tail(j);
848 r = sd_journal_previous(j);
854 r = sd_journal_get_realtime_usec(j, &id->last);
860 sd_journal_flush_matches(j);
863 qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
865 /* numbers are one less, but we need an extra char for the sign */
866 w = DECIMAL_STR_WIDTH(count - 1) + 1;
868 for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
869 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
871 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
873 SD_ID128_FORMAT_VAL(id->id),
874 format_timestamp(a, sizeof(a), id->first),
875 format_timestamp(b, sizeof(b), id->last));
881 static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
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;
892 r = sd_journal_query_unique(j, "_BOOT_ID");
896 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
897 if (length < strlen("_BOOT_ID="))
900 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
903 id = &all_ids[count];
905 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
909 r = sd_journal_add_match(j, data, length);
913 r = sd_journal_seek_head(j);
917 r = sd_journal_next(j);
923 r = sd_journal_get_realtime_usec(j, &id->first);
927 if (sd_id128_equal(id->id, *boot_id))
932 sd_journal_flush_matches(j);
935 qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
937 if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
938 if (relative > (int) count || relative <= -(int)count)
939 return -EADDRNOTAVAIL;
941 *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
943 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
946 relative <= 0 ? (id - all_ids) + relative < 0 :
947 (id - all_ids) + relative >= (int) count)
948 return -EADDRNOTAVAIL;
950 *boot_id = (id + relative)->id;
956 static int add_boot(sd_journal *j) {
957 char match[9+32+1] = "_BOOT_ID=";
965 if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
966 return add_match_this_boot(j, arg_machine);
968 r = get_relative_boot_id(j, &arg_boot_id, arg_boot_offset);
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));
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));
978 sd_id128_to_string(arg_boot_id, match + 9);
980 r = sd_journal_add_match(j, match, sizeof(match) - 1);
982 log_error("Failed to add match: %s", strerror(-r));
986 r = sd_journal_add_conjunction(j);
993 static int add_dmesg(sd_journal *j) {
1000 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1002 log_error("Failed to add match: %s", strerror(-r));
1006 r = sd_journal_add_conjunction(j);
1013 static int get_possible_units(sd_journal *j,
1017 _cleanup_set_free_free_ Set *found;
1021 found = set_new(string_hash_func, string_compare_func);
1025 NULSTR_FOREACH(field, fields) {
1029 r = sd_journal_query_unique(j, field);
1033 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1034 char **pattern, *eq;
1036 _cleanup_free_ char *u = NULL;
1038 eq = memchr(data, '=', size);
1040 prefix = eq - (char*) data + 1;
1044 u = strndup((char*) data + prefix, size - prefix);
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);
1052 r = set_consume(found, u);
1054 if (r < 0 && r != -EEXIST)
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 \
1073 "OBJECT_SYSTEMD_UNIT\0" \
1076 /* ... and add_matches_for_user_unit */
1077 #define USER_UNITS \
1078 "_SYSTEMD_USER_UNIT\0" \
1080 "COREDUMP_USER_UNIT\0" \
1081 "OBJECT_SYSTEMD_USER_UNIT\0"
1083 static int add_units(sd_journal *j) {
1084 _cleanup_strv_free_ char **patterns = NULL;
1090 STRV_FOREACH(i, arg_system_units) {
1091 _cleanup_free_ char *u = NULL;
1093 u = unit_name_mangle(*i, MANGLE_GLOB);
1097 if (string_is_glob(u)) {
1098 r = strv_push(&patterns, u);
1103 r = add_matches_for_unit(j, u);
1106 r = sd_journal_add_disjunction(j);
1113 if (!strv_isempty(patterns)) {
1114 _cleanup_set_free_free_ Set *units = NULL;
1118 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1122 SET_FOREACH(u, units, it) {
1123 r = add_matches_for_unit(j, u);
1126 r = sd_journal_add_disjunction(j);
1133 strv_free(patterns);
1136 STRV_FOREACH(i, arg_user_units) {
1137 _cleanup_free_ char *u = NULL;
1139 u = unit_name_mangle(*i, MANGLE_GLOB);
1143 if (string_is_glob(u)) {
1144 r = strv_push(&patterns, u);
1149 r = add_matches_for_user_unit(j, u, getuid());
1152 r = sd_journal_add_disjunction(j);
1159 if (!strv_isempty(patterns)) {
1160 _cleanup_set_free_free_ Set *units = NULL;
1164 r = get_possible_units(j, USER_UNITS, patterns, &units);
1168 SET_FOREACH(u, units, it) {
1169 r = add_matches_for_user_unit(j, u, getuid());
1172 r = sd_journal_add_disjunction(j);
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)
1184 r = sd_journal_add_conjunction(j);
1191 static int add_priorities(sd_journal *j) {
1192 char match[] = "PRIORITY=0";
1196 if (arg_priorities == 0xFF)
1199 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1200 if (arg_priorities & (1 << i)) {
1201 match[sizeof(match)-2] = '0' + i;
1203 r = sd_journal_add_match(j, match, strlen(match));
1205 log_error("Failed to add match: %s", strerror(-r));
1210 r = sd_journal_add_conjunction(j);
1217 static int setup_keys(void) {
1219 size_t mpk_size, seed_size, state_size, i;
1220 uint8_t *mpk, *seed, *state;
1222 int fd = -1, r, attr = 0;
1223 sd_id128_t machine, boot;
1224 char *p = NULL, *k = NULL;
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");
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;
1241 r = sd_id128_get_machine(&machine);
1243 log_error("Failed to get machine ID: %s", strerror(-r));
1247 r = sd_id128_get_boot(&boot);
1249 log_error("Failed to get boot ID: %s", strerror(-r));
1253 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1254 SD_ID128_FORMAT_VAL(machine)) < 0)
1257 if (access(p, F_OK) >= 0) {
1261 log_error("unlink(\"%s\") failed: %m", p);
1266 log_error("Sealing key file %s exists already. (--force to recreate)", p);
1272 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1273 SD_ID128_FORMAT_VAL(machine)) < 0) {
1278 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1279 mpk = alloca(mpk_size);
1281 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1282 seed = alloca(seed_size);
1284 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1285 state = alloca(state_size);
1287 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1289 log_error("Failed to open /dev/random: %m");
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));
1302 log_info("Generating key pair...");
1303 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1305 log_info("Generating sealing key...");
1306 FSPRG_GenState0(state, mpk, seed, seed_size);
1308 assert(arg_interval > 0);
1310 n = now(CLOCK_REALTIME);
1314 fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1316 log_error("Failed to open %s: %m", k);
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");
1326 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1328 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1329 log_warning("FS_IOC_SETFLAGS failed: %m");
1332 memcpy(h.signature, "KSHHRHLP", 8);
1333 h.machine_id = machine;
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);
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));
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));
1355 if (link(k, p) < 0) {
1356 log_error("Failed to link file: %m");
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"
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);
1375 for (i = 0; i < seed_size; i++) {
1376 if (i > 0 && i % 3 == 0)
1378 printf("%02x", ((uint8_t*) seed)[i]);
1381 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1384 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1387 ANSI_HIGHLIGHT_OFF "\n"
1388 "The sealing key is automatically changed every %s.\n",
1389 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1391 hn = gethostname_malloc();
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));
1397 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
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);
1423 log_error("Forward-secure sealing not available.");
1428 static int verify(sd_journal *j) {
1435 log_show_color(true);
1437 HASHMAP_FOREACH(f, j->files, i) {
1439 usec_t first, validated, last;
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);
1446 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1448 /* If the key was invalid give up right-away. */
1451 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1454 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1455 log_info("PASS: %s", f->path);
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));
1467 log_info("=> No sealing yet, no entries in file.");
1476 static int access_check_var_log_journal(sd_journal *j) {
1477 _cleanup_strv_free_ char **g = NULL;
1483 have_access = in_group("systemd-journal") > 0;
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);
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.");
1501 _cleanup_free_ char *s = NULL;
1503 r = strv_extend(&g, "systemd-journal");
1510 s = strv_join(g, "', '");
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);
1524 static int access_check(sd_journal *j) {
1531 if (set_isempty(j->errors)) {
1532 if (hashmap_isempty(j->files))
1533 log_notice("No journal files were found.");
1537 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
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 &&
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.");
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);
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.");
1564 if (hashmap_isempty(j->files)) {
1565 log_error("No journal files were opened due to insufficient permissions.");
1570 SET_FOREACH(code, j->errors, it) {
1573 err = -PTR_TO_INT(code);
1577 log_warning("Error was encountered while opening journal files: %s",
1584 int main(int argc, char *argv[]) {
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;
1591 bool ellipsized = false;
1593 setlocale(LC_ALL, "");
1594 log_parse_environment();
1597 r = parse_argv(argc, argv);
1601 signal(SIGWINCH, columns_lines_cache_reset);
1603 if (arg_action == ACTION_NEW_ID128) {
1604 r = generate_new_id128();
1608 if (arg_action == ACTION_SETUP_KEYS) {
1613 if (arg_action == ACTION_UPDATE_CATALOG ||
1614 arg_action == ACTION_LIST_CATALOG ||
1615 arg_action == ACTION_DUMP_CATALOG) {
1617 _cleanup_free_ char *database;
1619 database = path_join(arg_root, CATALOG_DATABASE, NULL);
1625 if (arg_action == ACTION_UPDATE_CATALOG) {
1626 r = catalog_update(database, arg_root, catalog_file_dirs);
1628 log_error("Failed to list catalog: %s", strerror(-r));
1630 bool oneline = arg_action == ACTION_LIST_CATALOG;
1633 r = catalog_list_items(stdout, database,
1634 oneline, argv + optind);
1636 r = catalog_list(stdout, database, oneline);
1638 log_error("Failed to list catalog: %s", strerror(-r));
1645 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1647 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1648 else if (arg_machine)
1649 r = sd_journal_open_container(&j, arg_machine, 0);
1651 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1653 log_error("Failed to open %s: %s",
1654 arg_directory ? arg_directory : arg_file ? "files" : "journal",
1656 return EXIT_FAILURE;
1659 r = access_check(j);
1661 return EXIT_FAILURE;
1663 if (arg_action == ACTION_VERIFY) {
1668 if (arg_action == ACTION_PRINT_HEADER) {
1669 journal_print_header(j);
1670 return EXIT_SUCCESS;
1673 if (arg_action == ACTION_DISK_USAGE) {
1675 char sbytes[FORMAT_BYTES_MAX];
1677 r = sd_journal_get_usage(j, &bytes);
1679 return EXIT_FAILURE;
1681 printf("Journals take up %s on disk.\n",
1682 format_bytes(sbytes, sizeof(sbytes), bytes));
1683 return EXIT_SUCCESS;
1686 if (arg_action == ACTION_LIST_BOOTS) {
1691 /* add_boot() must be called first!
1692 * It may need to seek the journal to find parent boot IDs. */
1695 return EXIT_FAILURE;
1699 return EXIT_FAILURE;
1702 strv_free(arg_system_units);
1703 strv_free(arg_user_units);
1706 log_error("Failed to add filter for units: %s", strerror(-r));
1707 return EXIT_FAILURE;
1710 r = add_priorities(j);
1712 log_error("Failed to add filter for priorities: %s", strerror(-r));
1713 return EXIT_FAILURE;
1716 r = add_matches(j, argv + optind);
1718 log_error("Failed to add filters: %s", strerror(-r));
1719 return EXIT_FAILURE;
1722 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1723 _cleanup_free_ char *filter;
1725 filter = journal_make_match_string(j);
1726 log_debug("Journal filter: %s", filter);
1733 r = sd_journal_set_data_threshold(j, 0);
1735 log_error("Failed to unset data size threshold");
1736 return EXIT_FAILURE;
1739 r = sd_journal_query_unique(j, arg_field);
1741 log_error("Failed to query unique data objects: %s", strerror(-r));
1742 return EXIT_FAILURE;
1745 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1748 if (arg_lines >= 0 && n_shown >= arg_lines)
1751 eq = memchr(data, '=', size);
1753 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1755 printf("%.*s\n", (int) size, (const char*) data);
1760 return EXIT_SUCCESS;
1763 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1765 r = sd_journal_get_fd(j);
1767 return EXIT_FAILURE;
1770 if (arg_cursor || arg_after_cursor) {
1771 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
1773 log_error("Failed to seek to cursor: %s", strerror(-r));
1774 return EXIT_FAILURE;
1777 r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1779 r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1781 if (arg_after_cursor && r < 2 && !arg_follow)
1782 /* We couldn't find the next entry after the cursor. */
1785 } else if (arg_since_set && !arg_reverse) {
1786 r = sd_journal_seek_realtime_usec(j, arg_since);
1788 log_error("Failed to seek to date: %s", strerror(-r));
1789 return EXIT_FAILURE;
1791 r = sd_journal_next(j);
1793 } else if (arg_until_set && arg_reverse) {
1794 r = sd_journal_seek_realtime_usec(j, arg_until);
1796 log_error("Failed to seek to date: %s", strerror(-r));
1797 return EXIT_FAILURE;
1799 r = sd_journal_previous(j);
1801 } else if (arg_lines >= 0) {
1802 r = sd_journal_seek_tail(j);
1804 log_error("Failed to seek to tail: %s", strerror(-r));
1805 return EXIT_FAILURE;
1808 r = sd_journal_previous_skip(j, arg_lines);
1810 } else if (arg_reverse) {
1811 r = sd_journal_seek_tail(j);
1813 log_error("Failed to seek to tail: %s", strerror(-r));
1814 return EXIT_FAILURE;
1817 r = sd_journal_previous(j);
1820 r = sd_journal_seek_head(j);
1822 log_error("Failed to seek to head: %s", strerror(-r));
1823 return EXIT_FAILURE;
1826 r = sd_journal_next(j);
1830 log_error("Failed to iterate through journal: %s", strerror(-r));
1831 return EXIT_FAILURE;
1835 pager_open_if_enabled();
1839 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1841 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1843 log_error("Failed to get cutoff: %s", strerror(-r));
1849 printf("-- Logs begin at %s. --\n",
1850 format_timestamp(start_buf, sizeof(start_buf), start));
1852 printf("-- Logs begin at %s, end at %s. --\n",
1853 format_timestamp(start_buf, sizeof(start_buf), start),
1854 format_timestamp(end_buf, sizeof(end_buf), end));
1859 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1864 r = sd_journal_next(j);
1866 r = sd_journal_previous(j);
1868 log_error("Failed to iterate through journal: %s", strerror(-r));
1875 if (arg_until_set && !arg_reverse) {
1878 r = sd_journal_get_realtime_usec(j, &usec);
1880 log_error("Failed to determine timestamp: %s", strerror(-r));
1883 if (usec > arg_until)
1887 if (arg_since_set && arg_reverse) {
1890 r = sd_journal_get_realtime_usec(j, &usec);
1892 log_error("Failed to determine timestamp: %s", strerror(-r));
1895 if (usec < arg_since)
1902 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1904 if (previous_boot_id_valid &&
1905 !sd_id128_equal(boot_id, previous_boot_id))
1906 printf("%s-- Reboot --%s\n",
1907 ansi_highlight(), ansi_highlight_off());
1909 previous_boot_id = boot_id;
1910 previous_boot_id_valid = true;
1915 arg_all * OUTPUT_SHOW_ALL |
1916 arg_full * OUTPUT_FULL_WIDTH |
1917 on_tty() * OUTPUT_COLOR |
1918 arg_catalog * OUTPUT_CATALOG;
1920 r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
1922 if (r == -EADDRNOTAVAIL)
1924 else if (r < 0 || ferror(stdout))
1931 if (arg_show_cursor) {
1932 _cleanup_free_ char *cursor = NULL;
1934 r = sd_journal_get_cursor(j, &cursor);
1935 if (r < 0 && r != -EADDRNOTAVAIL)
1936 log_error("Failed to get cursor: %s", strerror(-r));
1938 printf("-- cursor: %s\n", cursor);
1944 r = sd_journal_wait(j, (uint64_t) -1);
1946 log_error("Couldn't wait for journal event: %s", strerror(-r));
1956 strv_free(arg_file);
1958 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;