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/>.
34 #include <sys/ioctl.h>
42 #include <systemd/sd-journal.h>
45 #include "logs-show.h"
47 #include "path-util.h"
50 #include "logs-show.h"
52 #include "journal-internal.h"
53 #include "journal-def.h"
54 #include "journal-verify.h"
55 #include "journal-authenticate.h"
56 #include "journal-qrcode.h"
58 #include "unit-name.h"
61 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
63 static OutputMode arg_output = OUTPUT_SHORT;
64 static bool arg_pager_end = false;
65 static bool arg_follow = false;
66 static bool arg_full = false;
67 static bool arg_all = false;
68 static bool arg_no_pager = false;
69 static int arg_lines = -1;
70 static bool arg_no_tail = false;
71 static bool arg_quiet = false;
72 static bool arg_merge = false;
73 static bool arg_boot = false;
74 static char *arg_boot_descriptor = NULL;
75 static bool arg_dmesg = false;
76 static const char *arg_cursor = NULL;
77 static const char *arg_after_cursor = NULL;
78 static bool arg_show_cursor = false;
79 static const char *arg_directory = NULL;
80 static char **arg_file = NULL;
81 static int arg_priorities = 0xFF;
82 static const char *arg_verify_key = NULL;
84 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
85 static bool arg_force = false;
87 static usec_t arg_since, arg_until;
88 static bool arg_since_set = false, arg_until_set = false;
89 static char **arg_system_units = NULL;
90 static char **arg_user_units = NULL;
91 static const char *arg_field = NULL;
92 static bool arg_catalog = false;
93 static bool arg_reverse = false;
94 static int arg_journal_type = 0;
95 static const char *arg_root = NULL;
106 ACTION_UPDATE_CATALOG
107 } arg_action = ACTION_SHOW;
109 typedef struct boot_id_t {
114 static int help(void) {
116 printf("%s [OPTIONS...] [MATCHES...]\n\n"
117 "Query the journal.\n\n"
119 " --system Show only the system journal\n"
120 " --user Show only the user journal for current user\n"
121 " --since=DATE Start showing entries newer or of the specified date\n"
122 " --until=DATE Stop showing entries older or of the specified date\n"
123 " -c --cursor=CURSOR Start showing entries from specified cursor\n"
124 " --after-cursor=CURSOR Start showing entries from specified cursor\n"
125 " --show-cursor Print the cursor after all the entries\n"
126 " -b --boot[=ID] Show data only from ID or current boot if unspecified\n"
127 " -k --dmesg Show kernel message log from current boot\n"
128 " -u --unit=UNIT Show data only from the specified unit\n"
129 " --user-unit=UNIT Show data only from the specified user session unit\n"
130 " -p --priority=RANGE Show only messages within the specified priority range\n"
131 " -e --pager-end Immediately jump to end of the journal in the pager\n"
132 " -f --follow Follow journal\n"
133 " -n --lines[=INTEGER] Number of journal entries to show\n"
134 " --no-tail Show all lines, even in follow mode\n"
135 " -r --reverse Show the newest entries first\n"
136 " -o --output=STRING Change journal output mode (short, short-monotonic, short-iso\n"
137 " verbose, export, json, json-pretty, json-sse, cat)\n"
138 " -x --catalog Add message explanations where available\n"
139 " -l --full Do not ellipsize fields\n"
140 " -a --all Show all fields, including long and unprintable\n"
141 " -q --quiet Don't show privilege warning\n"
142 " --no-pager Do not pipe output into a pager\n"
143 " -m --merge Show entries from all available journals\n"
144 " -D --directory=PATH Show journal files from directory\n"
145 " --file=PATH Show journal file\n"
146 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
148 " --interval=TIME Time interval for changing the FSS sealing key\n"
149 " --verify-key=KEY Specify FSS verification key\n"
150 " --force Force overriding new FSS key pair with --setup-keys\n"
153 " -h --help Show this help\n"
154 " --version Show package version\n"
155 " --new-id128 Generate a new 128 Bit ID\n"
156 " --header Show journal header information\n"
157 " --disk-usage Show total disk usage\n"
158 " -F --field=FIELD List all values a certain field takes\n"
159 " --list-catalog Show message IDs of all entries in the message catalog\n"
160 " --dump-catalog Show entries in the message catalog\n"
161 " --update-catalog Update the message catalog database\n"
163 " --setup-keys Generate new FSS key pair\n"
164 " --verify Verify journal file consistency\n"
166 , program_invocation_short_name);
171 static int parse_argv(int argc, char *argv[]) {
199 static const struct option options[] = {
200 { "help", no_argument, NULL, 'h' },
201 { "version" , no_argument, NULL, ARG_VERSION },
202 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
203 { "pager-end", no_argument, NULL, 'e' },
204 { "follow", no_argument, NULL, 'f' },
205 { "force", no_argument, NULL, ARG_FORCE },
206 { "output", required_argument, NULL, 'o' },
207 { "all", no_argument, NULL, 'a' },
208 { "full", no_argument, NULL, 'l' },
209 { "lines", optional_argument, NULL, 'n' },
210 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
211 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
212 { "quiet", no_argument, NULL, 'q' },
213 { "merge", no_argument, NULL, 'm' },
214 { "boot", optional_argument, NULL, 'b' },
215 { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */
216 { "dmesg", no_argument, NULL, 'k' },
217 { "system", no_argument, NULL, ARG_SYSTEM },
218 { "user", no_argument, NULL, ARG_USER },
219 { "directory", required_argument, NULL, 'D' },
220 { "file", required_argument, NULL, ARG_FILE },
221 { "root", required_argument, NULL, ARG_ROOT },
222 { "header", no_argument, NULL, ARG_HEADER },
223 { "priority", required_argument, NULL, 'p' },
224 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
225 { "interval", required_argument, NULL, ARG_INTERVAL },
226 { "verify", no_argument, NULL, ARG_VERIFY },
227 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
228 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
229 { "cursor", required_argument, NULL, 'c' },
230 { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
231 { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
232 { "since", required_argument, NULL, ARG_SINCE },
233 { "until", required_argument, NULL, ARG_UNTIL },
234 { "unit", required_argument, NULL, 'u' },
235 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
236 { "field", required_argument, NULL, 'F' },
237 { "catalog", no_argument, NULL, 'x' },
238 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
239 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
240 { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
241 { "reverse", no_argument, NULL, 'r' },
250 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xr", options, NULL)) >= 0) {
259 puts(PACKAGE_STRING);
260 puts(SYSTEMD_FEATURES);
268 arg_pager_end = true;
280 arg_output = output_mode_from_string(optarg);
281 if (arg_output < 0) {
282 log_error("Unknown output format '%s'.", optarg);
286 if (arg_output == OUTPUT_EXPORT ||
287 arg_output == OUTPUT_JSON ||
288 arg_output == OUTPUT_JSON_PRETTY ||
289 arg_output == OUTPUT_JSON_SSE ||
290 arg_output == OUTPUT_CAT)
305 r = safe_atoi(optarg, &arg_lines);
306 if (r < 0 || arg_lines < 0) {
307 log_error("Failed to parse lines '%s'", optarg);
313 /* Hmm, no argument? Maybe the next
314 * word on the command line is
315 * supposed to be the argument? Let's
316 * see if there is one, and is
317 * parsable as a positive
321 safe_atoi(argv[optind], &n) >= 0 &&
337 arg_action = ACTION_NEW_ID128;
352 arg_boot_descriptor = optarg;
353 else if (optind < argc) {
356 if (argv[optind][0] != '-' ||
357 safe_atoi(argv[optind], &boot) >= 0) {
358 arg_boot_descriptor = argv[optind];
366 arg_boot = arg_dmesg = true;
370 arg_journal_type |= SD_JOURNAL_SYSTEM;
374 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
378 arg_directory = optarg;
382 r = glob_extend(&arg_file, optarg);
384 log_error("Failed to add paths: %s", strerror(-r));
397 case ARG_AFTER_CURSOR:
398 arg_after_cursor = optarg;
401 case ARG_SHOW_CURSOR:
402 arg_show_cursor = true;
406 arg_action = ACTION_PRINT_HEADER;
410 arg_action = ACTION_VERIFY;
414 arg_action = ACTION_DISK_USAGE;
423 arg_action = ACTION_SETUP_KEYS;
428 arg_action = ACTION_VERIFY;
429 arg_verify_key = optarg;
434 r = parse_sec(optarg, &arg_interval);
435 if (r < 0 || arg_interval <= 0) {
436 log_error("Failed to parse sealing key change interval: %s", optarg);
445 log_error("Forward-secure sealing not available.");
452 dots = strstr(optarg, "..");
458 a = strndup(optarg, dots - optarg);
462 from = log_level_from_string(a);
463 to = log_level_from_string(dots + 2);
466 if (from < 0 || to < 0) {
467 log_error("Failed to parse log level range %s", optarg);
474 for (i = from; i <= to; i++)
475 arg_priorities |= 1 << i;
477 for (i = to; i <= from; i++)
478 arg_priorities |= 1 << i;
484 p = log_level_from_string(optarg);
486 log_error("Unknown log level %s", optarg);
492 for (i = 0; i <= p; i++)
493 arg_priorities |= 1 << i;
500 r = parse_timestamp(optarg, &arg_since);
502 log_error("Failed to parse timestamp: %s", optarg);
505 arg_since_set = true;
509 r = parse_timestamp(optarg, &arg_until);
511 log_error("Failed to parse timestamp: %s", optarg);
514 arg_until_set = true;
518 r = strv_extend(&arg_system_units, optarg);
524 r = strv_extend(&arg_user_units, optarg);
540 case ARG_LIST_CATALOG:
541 arg_action = ACTION_LIST_CATALOG;
544 case ARG_DUMP_CATALOG:
545 arg_action = ACTION_DUMP_CATALOG;
548 case ARG_UPDATE_CATALOG:
549 arg_action = ACTION_UPDATE_CATALOG;
557 log_error("Unknown option code %c", c);
562 if (arg_follow && !arg_no_tail && arg_lines < 0)
565 if (arg_directory && arg_file) {
566 log_error("Please specify either -D/--directory= or --file=, not both.");
570 if (arg_since_set && arg_until_set && arg_since > arg_until) {
571 log_error("--since= must be before --until=.");
575 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
576 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
580 if (arg_follow && arg_reverse) {
581 log_error("Please specify either --reverse= or --follow=, not both.");
588 static int generate_new_id128(void) {
593 r = sd_id128_randomize(&id);
595 log_error("Failed to generate ID: %s", strerror(-r));
599 printf("As string:\n"
600 SD_ID128_FORMAT_STR "\n\n"
602 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
604 "#define MESSAGE_XYZ SD_ID128_MAKE(",
605 SD_ID128_FORMAT_VAL(id),
606 SD_ID128_FORMAT_VAL(id));
607 for (i = 0; i < 16; i++)
608 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
609 fputs(")\n\n", stdout);
611 printf("As Python constant:\n"
613 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
614 SD_ID128_FORMAT_VAL(id));
619 static int add_matches(sd_journal *j, char **args) {
624 STRV_FOREACH(i, args) {
628 r = sd_journal_add_disjunction(j);
629 else if (path_is_absolute(*i)) {
630 _cleanup_free_ char *p, *t = NULL;
634 p = canonicalize_file_name(*i);
637 if (stat(path, &st) < 0) {
638 log_error("Couldn't stat file: %m");
642 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
643 t = strappend("_EXE=", path);
644 else if (S_ISCHR(st.st_mode))
645 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
646 else if (S_ISBLK(st.st_mode))
647 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
649 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
656 r = sd_journal_add_match(j, t, 0);
658 r = sd_journal_add_match(j, *i, 0);
661 log_error("Failed to add match '%s': %s", *i, strerror(-r));
669 static int boot_id_cmp(const void *a, const void *b) {
672 _a = ((const boot_id_t *)a)->timestamp;
673 _b = ((const boot_id_t *)b)->timestamp;
675 return _a < _b ? -1 : (_a > _b ? 1 : 0);
678 static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
681 unsigned int count = 0;
682 size_t length, allocated = 0;
683 boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
684 _cleanup_free_ boot_id_t *all_ids = NULL;
689 if (relative == 0 && !sd_id128_equal(*boot_id, SD_ID128_NULL))
692 r = sd_journal_query_unique(j, "_BOOT_ID");
696 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
697 if (length < strlen("_BOOT_ID="))
700 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
703 id = &all_ids[count];
705 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
709 r = sd_journal_add_match(j, data, length);
713 r = sd_journal_seek_head(j);
717 r = sd_journal_next(j);
723 r = sd_journal_get_realtime_usec(j, &id->timestamp);
727 if (sd_id128_equal(id->id, *boot_id))
732 sd_journal_flush_matches(j);
735 qsort(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
737 if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
738 if (relative > (int) count || relative <= -(int)count)
739 return -EADDRNOTAVAIL;
741 *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
743 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
746 relative <= 0 ? (id - all_ids) + relative < 0 :
747 (id - all_ids) + relative >= (int) count)
748 return -EADDRNOTAVAIL;
750 *boot_id = (id + relative)->id;
756 static int add_boot(sd_journal *j) {
757 char match[9+32+1] = "_BOOT_ID=";
759 sd_id128_t boot_id = SD_ID128_NULL;
767 if (!arg_boot_descriptor)
768 return add_match_this_boot(j);
770 if (strlen(arg_boot_descriptor) >= 32) {
771 char tmp = arg_boot_descriptor[32];
772 arg_boot_descriptor[32] = '\0';
773 r = sd_id128_from_string(arg_boot_descriptor, &boot_id);
774 arg_boot_descriptor[32] = tmp;
777 log_error("Failed to parse boot ID '%.32s': %s",
778 arg_boot_descriptor, strerror(-r));
782 offset = arg_boot_descriptor + 32;
784 if (*offset && *offset != '-' && *offset != '+') {
785 log_error("Relative boot ID offset must start with a '+' or a '-', found '%s' ", offset);
789 offset = arg_boot_descriptor;
792 r = safe_atoi(offset, &relative);
794 log_error("Failed to parse relative boot ID number '%s'", offset);
799 r = get_relative_boot_id(j, &boot_id, relative);
801 if (sd_id128_equal(boot_id, SD_ID128_NULL))
802 log_error("Failed to look up boot %+d: %s", relative, strerror(-r));
804 log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+d: %s",
805 SD_ID128_FORMAT_VAL(boot_id), relative, strerror(-r));
809 sd_id128_to_string(boot_id, match + 9);
811 r = sd_journal_add_match(j, match, sizeof(match) - 1);
813 log_error("Failed to add match: %s", strerror(-r));
817 r = sd_journal_add_conjunction(j);
824 static int add_dmesg(sd_journal *j) {
831 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
833 log_error("Failed to add match: %s", strerror(-r));
837 r = sd_journal_add_conjunction(j);
844 static int add_units(sd_journal *j) {
845 _cleanup_free_ char *u = NULL;
851 STRV_FOREACH(i, arg_system_units) {
852 u = unit_name_mangle(*i);
855 r = add_matches_for_unit(j, u);
858 r = sd_journal_add_disjunction(j);
863 STRV_FOREACH(i, arg_user_units) {
864 u = unit_name_mangle(*i);
868 r = add_matches_for_user_unit(j, u, getuid());
872 r = sd_journal_add_disjunction(j);
878 r = sd_journal_add_conjunction(j);
885 static int add_priorities(sd_journal *j) {
886 char match[] = "PRIORITY=0";
890 if (arg_priorities == 0xFF)
893 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
894 if (arg_priorities & (1 << i)) {
895 match[sizeof(match)-2] = '0' + i;
897 r = sd_journal_add_match(j, match, strlen(match));
899 log_error("Failed to add match: %s", strerror(-r));
904 r = sd_journal_add_conjunction(j);
911 static int setup_keys(void) {
913 size_t mpk_size, seed_size, state_size, i;
914 uint8_t *mpk, *seed, *state;
916 int fd = -1, r, attr = 0;
917 sd_id128_t machine, boot;
918 char *p = NULL, *k = NULL;
923 r = stat("/var/log/journal", &st);
924 if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
925 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
929 if (r < 0 || !S_ISDIR(st.st_mode)) {
930 log_error("%s is not a directory, must be using persistent logging for FSS.",
932 return r < 0 ? -errno : -ENOTDIR;
935 r = sd_id128_get_machine(&machine);
937 log_error("Failed to get machine ID: %s", strerror(-r));
941 r = sd_id128_get_boot(&boot);
943 log_error("Failed to get boot ID: %s", strerror(-r));
947 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
948 SD_ID128_FORMAT_VAL(machine)) < 0)
951 if (access(p, F_OK) >= 0) {
955 log_error("unlink(\"%s\") failed: %m", p);
960 log_error("Sealing key file %s exists already. (--force to recreate)", p);
966 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
967 SD_ID128_FORMAT_VAL(machine)) < 0) {
972 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
973 mpk = alloca(mpk_size);
975 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
976 seed = alloca(seed_size);
978 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
979 state = alloca(state_size);
981 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
983 log_error("Failed to open /dev/random: %m");
988 log_info("Generating seed...");
989 l = loop_read(fd, seed, seed_size, true);
990 if (l < 0 || (size_t) l != seed_size) {
991 log_error("Failed to read random seed: %s", strerror(EIO));
996 log_info("Generating key pair...");
997 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
999 log_info("Generating sealing key...");
1000 FSPRG_GenState0(state, mpk, seed, seed_size);
1002 assert(arg_interval > 0);
1004 n = now(CLOCK_REALTIME);
1007 close_nointr_nofail(fd);
1008 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
1010 log_error("Failed to open %s: %m", k);
1015 /* Enable secure remove, exclusion from dump, synchronous
1016 * writing and in-place updating */
1017 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
1018 log_warning("FS_IOC_GETFLAGS failed: %m");
1020 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1022 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1023 log_warning("FS_IOC_SETFLAGS failed: %m");
1026 memcpy(h.signature, "KSHHRHLP", 8);
1027 h.machine_id = machine;
1029 h.header_size = htole64(sizeof(h));
1030 h.start_usec = htole64(n * arg_interval);
1031 h.interval_usec = htole64(arg_interval);
1032 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1033 h.fsprg_state_size = htole64(state_size);
1035 l = loop_write(fd, &h, sizeof(h), false);
1036 if (l < 0 || (size_t) l != sizeof(h)) {
1037 log_error("Failed to write header: %s", strerror(EIO));
1042 l = loop_write(fd, state, state_size, false);
1043 if (l < 0 || (size_t) l != state_size) {
1044 log_error("Failed to write state: %s", strerror(EIO));
1049 if (link(k, p) < 0) {
1050 log_error("Failed to link file: %m");
1058 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
1059 "the following local file. This key file is automatically updated when the\n"
1060 "sealing key is advanced. It should not be used on multiple hosts.\n"
1064 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
1065 "at a safe location and should not be saved locally on disk.\n"
1066 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
1069 for (i = 0; i < seed_size; i++) {
1070 if (i > 0 && i % 3 == 0)
1072 printf("%02x", ((uint8_t*) seed)[i]);
1075 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1078 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1081 ANSI_HIGHLIGHT_OFF "\n"
1082 "The sealing key is automatically changed every %s.\n",
1083 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1085 hn = gethostname_malloc();
1088 hostname_cleanup(hn, false);
1089 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1091 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1093 #ifdef HAVE_QRENCODE
1094 /* If this is not an UTF-8 system don't print any QR codes */
1095 if (is_locale_utf8()) {
1096 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1097 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1107 close_nointr_nofail(fd);
1118 log_error("Forward-secure sealing not available.");
1123 static int verify(sd_journal *j) {
1130 log_show_color(true);
1132 HASHMAP_FOREACH(f, j->files, i) {
1134 usec_t first, validated, last;
1137 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1138 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1141 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1143 /* If the key was invalid give up right-away. */
1146 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1149 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1150 log_info("PASS: %s", f->path);
1152 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1153 if (validated > 0) {
1154 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1155 format_timestamp(a, sizeof(a), first),
1156 format_timestamp(b, sizeof(b), validated),
1157 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1158 } else if (last > 0)
1159 log_info("=> No sealing yet, %s of entries not sealed.",
1160 format_timespan(c, sizeof(c), last - first, 0));
1162 log_info("=> No sealing yet, no entries in file.");
1171 static int access_check_var_log_journal(sd_journal *j) {
1172 _cleanup_strv_free_ char **g = NULL;
1178 have_access = in_group("systemd-journal") > 0;
1181 /* Let's enumerate all groups from the default ACL of
1182 * the directory, which generally should allow access
1183 * to most journal files too */
1184 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1191 if (strv_isempty(g))
1192 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1193 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1194 " turn off this notice.");
1196 _cleanup_free_ char *s = NULL;
1198 r = strv_extend(&g, "systemd-journal");
1205 s = strv_join(g, "', '");
1209 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1210 " Users in the groups '%s' can see all messages.\n"
1211 " Pass -q to turn off this notice.", s);
1219 static int access_check(sd_journal *j) {
1226 if (set_isempty(j->errors)) {
1227 if (hashmap_isempty(j->files))
1228 log_notice("No journal files were found.");
1232 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1234 /* If /var/log/journal doesn't even exist,
1235 * unprivileged users have no access at all */
1236 if (access("/var/log/journal", F_OK) < 0 &&
1238 in_group("systemd-journal") <= 0) {
1239 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1240 "enabled. Users in the 'systemd-journal' group may always access messages.");
1244 /* If /var/log/journal exists, try to pring a nice
1245 notice if the user lacks access to it */
1246 if (!arg_quiet && geteuid() != 0) {
1247 r = access_check_var_log_journal(j);
1252 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1253 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1254 "group may access messages.");
1259 if (hashmap_isempty(j->files)) {
1260 log_error("No journal files were opened due to insufficient permissions.");
1265 SET_FOREACH(code, j->errors, it) {
1268 err = -PTR_TO_INT(code);
1272 log_warning("Error was encountered while opening journal files: %s",
1279 int main(int argc, char *argv[]) {
1281 _cleanup_journal_close_ sd_journal*j = NULL;
1282 bool need_seek = false;
1283 sd_id128_t previous_boot_id;
1284 bool previous_boot_id_valid = false, first_line = true;
1287 setlocale(LC_ALL, "");
1288 log_parse_environment();
1291 r = parse_argv(argc, argv);
1295 signal(SIGWINCH, columns_lines_cache_reset);
1297 if (arg_action == ACTION_NEW_ID128) {
1298 r = generate_new_id128();
1302 if (arg_action == ACTION_SETUP_KEYS) {
1307 if (arg_action == ACTION_UPDATE_CATALOG ||
1308 arg_action == ACTION_LIST_CATALOG ||
1309 arg_action == ACTION_DUMP_CATALOG) {
1311 const char* database = CATALOG_DATABASE;
1312 _cleanup_free_ char *copy = NULL;
1314 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1319 path_kill_slashes(copy);
1323 if (arg_action == ACTION_UPDATE_CATALOG) {
1324 r = catalog_update(database, arg_root, catalog_file_dirs);
1326 log_error("Failed to list catalog: %s", strerror(-r));
1328 bool oneline = arg_action == ACTION_LIST_CATALOG;
1331 r = catalog_list_items(stdout, database,
1332 oneline, argv + optind);
1334 r = catalog_list(stdout, database, oneline);
1336 log_error("Failed to list catalog: %s", strerror(-r));
1343 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1345 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1347 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1349 log_error("Failed to open %s: %s",
1350 arg_directory ? arg_directory : arg_file ? "files" : "journal",
1352 return EXIT_FAILURE;
1355 r = access_check(j);
1357 return EXIT_FAILURE;
1359 if (arg_action == ACTION_VERIFY) {
1364 if (arg_action == ACTION_PRINT_HEADER) {
1365 journal_print_header(j);
1366 return EXIT_SUCCESS;
1369 if (arg_action == ACTION_DISK_USAGE) {
1371 char sbytes[FORMAT_BYTES_MAX];
1373 r = sd_journal_get_usage(j, &bytes);
1375 return EXIT_FAILURE;
1377 printf("Journals take up %s on disk.\n",
1378 format_bytes(sbytes, sizeof(sbytes), bytes));
1379 return EXIT_SUCCESS;
1382 /* add_boot() must be called first!
1383 * It may need to seek the journal to find parent boot IDs. */
1386 return EXIT_FAILURE;
1390 return EXIT_FAILURE;
1393 strv_free(arg_system_units);
1394 strv_free(arg_user_units);
1397 return EXIT_FAILURE;
1399 r = add_priorities(j);
1401 return EXIT_FAILURE;
1403 r = add_matches(j, argv + optind);
1405 return EXIT_FAILURE;
1407 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1408 _cleanup_free_ char *filter;
1410 filter = journal_make_match_string(j);
1411 log_debug("Journal filter: %s", filter);
1418 r = sd_journal_set_data_threshold(j, 0);
1420 log_error("Failed to unset data size threshold");
1421 return EXIT_FAILURE;
1424 r = sd_journal_query_unique(j, arg_field);
1426 log_error("Failed to query unique data objects: %s", strerror(-r));
1427 return EXIT_FAILURE;
1430 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1433 if (arg_lines >= 0 && n_shown >= arg_lines)
1436 eq = memchr(data, '=', size);
1438 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1440 printf("%.*s\n", (int) size, (const char*) data);
1445 return EXIT_SUCCESS;
1448 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1450 r = sd_journal_get_fd(j);
1452 return EXIT_FAILURE;
1455 if (arg_cursor || arg_after_cursor) {
1456 r = sd_journal_seek_cursor(j, arg_cursor ? arg_cursor : arg_after_cursor);
1458 log_error("Failed to seek to cursor: %s", strerror(-r));
1459 return EXIT_FAILURE;
1462 r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1464 r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1466 if (arg_after_cursor && r < 2 && !arg_follow)
1467 /* We couldn't find the next entry after the cursor. */
1470 } else if (arg_since_set && !arg_reverse) {
1471 r = sd_journal_seek_realtime_usec(j, arg_since);
1473 log_error("Failed to seek to date: %s", strerror(-r));
1474 return EXIT_FAILURE;
1476 r = sd_journal_next(j);
1478 } else if (arg_until_set && arg_reverse) {
1479 r = sd_journal_seek_realtime_usec(j, arg_until);
1481 log_error("Failed to seek to date: %s", strerror(-r));
1482 return EXIT_FAILURE;
1484 r = sd_journal_previous(j);
1486 } else if (arg_lines >= 0) {
1487 r = sd_journal_seek_tail(j);
1489 log_error("Failed to seek to tail: %s", strerror(-r));
1490 return EXIT_FAILURE;
1493 r = sd_journal_previous_skip(j, arg_lines);
1495 } else if (arg_reverse) {
1496 r = sd_journal_seek_tail(j);
1498 log_error("Failed to seek to tail: %s", strerror(-r));
1499 return EXIT_FAILURE;
1502 r = sd_journal_previous(j);
1505 r = sd_journal_seek_head(j);
1507 log_error("Failed to seek to head: %s", strerror(-r));
1508 return EXIT_FAILURE;
1511 r = sd_journal_next(j);
1515 log_error("Failed to iterate through journal: %s", strerror(-r));
1516 return EXIT_FAILURE;
1519 if (!arg_no_pager && !arg_follow)
1520 pager_open(arg_pager_end);
1524 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1526 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1528 log_error("Failed to get cutoff: %s", strerror(-r));
1534 printf("-- Logs begin at %s. --\n",
1535 format_timestamp(start_buf, sizeof(start_buf), start));
1537 printf("-- Logs begin at %s, end at %s. --\n",
1538 format_timestamp(start_buf, sizeof(start_buf), start),
1539 format_timestamp(end_buf, sizeof(end_buf), end));
1544 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1549 r = sd_journal_next(j);
1551 r = sd_journal_previous(j);
1553 log_error("Failed to iterate through journal: %s", strerror(-r));
1560 if (arg_until_set && !arg_reverse) {
1563 r = sd_journal_get_realtime_usec(j, &usec);
1565 log_error("Failed to determine timestamp: %s", strerror(-r));
1568 if (usec > arg_until)
1572 if (arg_since_set && arg_reverse) {
1575 r = sd_journal_get_realtime_usec(j, &usec);
1577 log_error("Failed to determine timestamp: %s", strerror(-r));
1580 if (usec < arg_since)
1586 const char *color_on = on_tty() ? ANSI_HIGHLIGHT_ON : "",
1587 *color_off = on_tty() ? ANSI_HIGHLIGHT_OFF : "";
1589 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1591 if (previous_boot_id_valid &&
1592 !sd_id128_equal(boot_id, previous_boot_id))
1593 printf("%s-- Reboot --%s\n", color_on, color_off);
1595 previous_boot_id = boot_id;
1596 previous_boot_id_valid = true;
1601 arg_all * OUTPUT_SHOW_ALL |
1602 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1603 on_tty() * OUTPUT_COLOR |
1604 arg_catalog * OUTPUT_CATALOG;
1606 r = output_journal(stdout, j, arg_output, 0, flags);
1608 if (r == -EADDRNOTAVAIL)
1610 else if (r < 0 || ferror(stdout))
1617 if (arg_show_cursor) {
1618 _cleanup_free_ char *cursor = NULL;
1620 r = sd_journal_get_cursor(j, &cursor);
1621 if (r < 0 && r != -EADDRNOTAVAIL)
1622 log_error("Failed to get cursor: %s", strerror(-r));
1624 printf("-- cursor: %s\n", cursor);
1630 r = sd_journal_wait(j, (uint64_t) -1);
1632 log_error("Couldn't wait for journal event: %s", strerror(-r));
1642 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;