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_this_boot = false;
74 static bool arg_dmesg = false;
75 static const char *arg_cursor = NULL;
76 static const char *arg_directory = NULL;
77 static char **arg_file = NULL;
78 static int arg_priorities = 0xFF;
79 static const char *arg_verify_key = NULL;
81 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
83 static usec_t arg_since, arg_until;
84 static bool arg_since_set = false, arg_until_set = false;
85 static char **arg_system_units = NULL;
86 static char **arg_user_units = NULL;
87 static const char *arg_field = NULL;
88 static bool arg_catalog = false;
89 static bool arg_reverse = false;
90 static int arg_journal_type = 0;
91 static const char *arg_root = NULL;
102 ACTION_UPDATE_CATALOG
103 } arg_action = ACTION_SHOW;
105 static int help(void) {
107 printf("%s [OPTIONS...] [MATCHES...]\n\n"
108 "Query the journal.\n\n"
110 " --system Show only the system journal\n"
111 " --user Show only the user journal for current user\n"
112 " --since=DATE Start showing entries newer or of the specified date\n"
113 " --until=DATE Stop showing entries older or of the specified date\n"
114 " -c --cursor=CURSOR Start showing entries from specified cursor\n"
115 " -b --this-boot Show data only from current boot\n"
116 " -k --dmesg Show kmsg log from current boot\n"
117 " -u --unit=UNIT Show data only from the specified unit\n"
118 " --user-unit=UNIT Show data only from the specified user session unit\n"
119 " -p --priority=RANGE Show only messages within the specified priority range\n"
120 " -e --pager-end Immediately jump to end of the journal in the pager\n"
121 " -f --follow Follow journal\n"
122 " -n --lines[=INTEGER] Number of journal entries to show\n"
123 " --no-tail Show all lines, even in follow mode\n"
124 " -r --reverse Show the newest entries first\n"
125 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
126 " verbose, export, json, json-pretty, json-sse, cat)\n"
127 " -x --catalog Add message explanations where available\n"
128 " --full Do not ellipsize fields\n"
129 " -a --all Show all fields, including long and unprintable\n"
130 " -q --quiet Don't show privilege warning\n"
131 " --no-pager Do not pipe output into a pager\n"
132 " -m --merge Show entries from all available journals\n"
133 " -D --directory=PATH Show journal files from directory\n"
134 " --file=PATH Show journal file\n"
135 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
137 " --interval=TIME Time interval for changing the FSS sealing key\n"
138 " --verify-key=KEY Specify FSS verification key\n"
141 " -h --help Show this help\n"
142 " --version Show package version\n"
143 " --new-id128 Generate a new 128 Bit ID\n"
144 " --header Show journal header information\n"
145 " --disk-usage Show total disk usage\n"
146 " -F --field=FIELD List all values a certain field takes\n"
147 " --list-catalog Show message IDs of all entries in the message catalog\n"
148 " --dump-catalog Show entries in the message catalog\n"
149 " --update-catalog Update the message catalog database\n"
151 " --setup-keys Generate new FSS key pair\n"
152 " --verify Verify journal file consistency\n"
154 , program_invocation_short_name);
159 static int parse_argv(int argc, char *argv[]) {
185 static const struct option options[] = {
186 { "help", no_argument, NULL, 'h' },
187 { "version" , no_argument, NULL, ARG_VERSION },
188 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
189 { "pager-end", no_argument, NULL, 'e' },
190 { "follow", no_argument, NULL, 'f' },
191 { "output", required_argument, NULL, 'o' },
192 { "all", no_argument, NULL, 'a' },
193 { "full", no_argument, NULL, ARG_FULL },
194 { "lines", optional_argument, NULL, 'n' },
195 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
196 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
197 { "quiet", no_argument, NULL, 'q' },
198 { "merge", no_argument, NULL, 'm' },
199 { "this-boot", no_argument, NULL, 'b' },
200 { "dmesg", no_argument, NULL, 'k' },
201 { "system", no_argument, NULL, ARG_SYSTEM },
202 { "user", no_argument, NULL, ARG_USER },
203 { "directory", required_argument, NULL, 'D' },
204 { "file", required_argument, NULL, ARG_FILE },
205 { "root", required_argument, NULL, ARG_ROOT },
206 { "header", no_argument, NULL, ARG_HEADER },
207 { "priority", required_argument, NULL, 'p' },
208 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
209 { "interval", required_argument, NULL, ARG_INTERVAL },
210 { "verify", no_argument, NULL, ARG_VERIFY },
211 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
212 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
213 { "cursor", required_argument, NULL, 'c' },
214 { "since", required_argument, NULL, ARG_SINCE },
215 { "until", required_argument, NULL, ARG_UNTIL },
216 { "unit", required_argument, NULL, 'u' },
217 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
218 { "field", required_argument, NULL, 'F' },
219 { "catalog", no_argument, NULL, 'x' },
220 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
221 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
222 { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
223 { "reverse", no_argument, NULL, 'r' },
232 while ((c = getopt_long(argc, argv, "hefo:an::qmbkD:p:c:u:F:xr", options, NULL)) >= 0) {
241 puts(PACKAGE_STRING);
242 puts(SYSTEMD_FEATURES);
250 arg_pager_end = true;
262 arg_output = output_mode_from_string(optarg);
263 if (arg_output < 0) {
264 log_error("Unknown output format '%s'.", optarg);
268 if (arg_output == OUTPUT_EXPORT ||
269 arg_output == OUTPUT_JSON ||
270 arg_output == OUTPUT_JSON_PRETTY ||
271 arg_output == OUTPUT_JSON_SSE ||
272 arg_output == OUTPUT_CAT)
287 r = safe_atoi(optarg, &arg_lines);
288 if (r < 0 || arg_lines < 0) {
289 log_error("Failed to parse lines '%s'", optarg);
295 /* Hmm, no argument? Maybe the next
296 * word on the command line is
297 * supposed to be the argument? Let's
298 * see if there is one, and is
299 * parsable as a positive
303 safe_atoi(argv[optind], &n) >= 0 &&
319 arg_action = ACTION_NEW_ID128;
331 arg_this_boot = true;
335 arg_this_boot = arg_dmesg = true;
339 arg_journal_type |= SD_JOURNAL_SYSTEM;
343 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
347 arg_directory = optarg;
351 r = glob_extend(&arg_file, optarg);
353 log_error("Failed to add paths: %s", strerror(-r));
367 arg_action = ACTION_PRINT_HEADER;
371 arg_action = ACTION_VERIFY;
375 arg_action = ACTION_DISK_USAGE;
380 arg_action = ACTION_SETUP_KEYS;
385 arg_action = ACTION_VERIFY;
386 arg_verify_key = optarg;
391 r = parse_sec(optarg, &arg_interval);
392 if (r < 0 || arg_interval <= 0) {
393 log_error("Failed to parse sealing key change interval: %s", optarg);
401 log_error("Forward-secure sealing not available.");
408 dots = strstr(optarg, "..");
414 a = strndup(optarg, dots - optarg);
418 from = log_level_from_string(a);
419 to = log_level_from_string(dots + 2);
422 if (from < 0 || to < 0) {
423 log_error("Failed to parse log level range %s", optarg);
430 for (i = from; i <= to; i++)
431 arg_priorities |= 1 << i;
433 for (i = to; i <= from; i++)
434 arg_priorities |= 1 << i;
440 p = log_level_from_string(optarg);
442 log_error("Unknown log level %s", optarg);
448 for (i = 0; i <= p; i++)
449 arg_priorities |= 1 << i;
456 r = parse_timestamp(optarg, &arg_since);
458 log_error("Failed to parse timestamp: %s", optarg);
461 arg_since_set = true;
465 r = parse_timestamp(optarg, &arg_until);
467 log_error("Failed to parse timestamp: %s", optarg);
470 arg_until_set = true;
474 r = strv_extend(&arg_system_units, optarg);
480 r = strv_extend(&arg_user_units, optarg);
496 case ARG_LIST_CATALOG:
497 arg_action = ACTION_LIST_CATALOG;
500 case ARG_DUMP_CATALOG:
501 arg_action = ACTION_DUMP_CATALOG;
504 case ARG_UPDATE_CATALOG:
505 arg_action = ACTION_UPDATE_CATALOG;
513 log_error("Unknown option code %c", c);
518 if (arg_follow && !arg_no_tail && arg_lines < 0)
521 if (arg_directory && arg_file) {
522 log_error("Please specify either -D/--directory= or --file=, not both.");
526 if (arg_since_set && arg_until_set && arg_since > arg_until) {
527 log_error("--since= must be before --until=.");
531 if (arg_cursor && arg_since_set) {
532 log_error("Please specify either --since= or --cursor=, not both.");
536 if (arg_follow && arg_reverse) {
537 log_error("Please specify either --reverse= or --follow=, not both.");
544 static int generate_new_id128(void) {
549 r = sd_id128_randomize(&id);
551 log_error("Failed to generate ID: %s", strerror(-r));
555 printf("As string:\n"
556 SD_ID128_FORMAT_STR "\n\n"
558 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
560 "#define MESSAGE_XYZ SD_ID128_MAKE(",
561 SD_ID128_FORMAT_VAL(id),
562 SD_ID128_FORMAT_VAL(id));
563 for (i = 0; i < 16; i++)
564 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
565 fputs(")\n\n", stdout);
567 printf("As Python constant:\n"
569 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
570 SD_ID128_FORMAT_VAL(id));
575 static int add_matches(sd_journal *j, char **args) {
580 STRV_FOREACH(i, args) {
584 r = sd_journal_add_disjunction(j);
585 else if (path_is_absolute(*i)) {
586 _cleanup_free_ char *p, *t = NULL;
590 p = canonicalize_file_name(*i);
593 if (stat(path, &st) < 0) {
594 log_error("Couldn't stat file: %m");
598 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
599 t = strappend("_EXE=", path);
600 else if (S_ISCHR(st.st_mode))
601 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
602 else if (S_ISBLK(st.st_mode))
603 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
605 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
612 r = sd_journal_add_match(j, t, 0);
614 r = sd_journal_add_match(j, *i, 0);
617 log_error("Failed to add match '%s': %s", *i, strerror(-r));
625 static int add_this_boot(sd_journal *j) {
629 return add_match_this_boot(j);
632 static int add_dmesg(sd_journal *j) {
639 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
641 log_error("Failed to add match: %s", strerror(-r));
645 r = sd_journal_add_conjunction(j);
652 static int add_units(sd_journal *j) {
653 _cleanup_free_ char *u = NULL;
659 STRV_FOREACH(i, arg_system_units) {
660 u = unit_name_mangle(*i);
663 r = add_matches_for_unit(j, u);
666 r = sd_journal_add_disjunction(j);
671 STRV_FOREACH(i, arg_user_units) {
672 u = unit_name_mangle(*i);
676 r = add_matches_for_user_unit(j, u, getuid());
680 r = sd_journal_add_disjunction(j);
686 r = sd_journal_add_conjunction(j);
693 static int add_priorities(sd_journal *j) {
694 char match[] = "PRIORITY=0";
698 if (arg_priorities == 0xFF)
701 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
702 if (arg_priorities & (1 << i)) {
703 match[sizeof(match)-2] = '0' + i;
705 r = sd_journal_add_match(j, match, strlen(match));
707 log_error("Failed to add match: %s", strerror(-r));
712 r = sd_journal_add_conjunction(j);
719 static int setup_keys(void) {
721 size_t mpk_size, seed_size, state_size, i;
722 uint8_t *mpk, *seed, *state;
724 int fd = -1, r, attr = 0;
725 sd_id128_t machine, boot;
726 char *p = NULL, *k = NULL;
730 r = sd_id128_get_machine(&machine);
732 log_error("Failed to get machine ID: %s", strerror(-r));
736 r = sd_id128_get_boot(&boot);
738 log_error("Failed to get boot ID: %s", strerror(-r));
742 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
743 SD_ID128_FORMAT_VAL(machine)) < 0)
746 if (access(p, F_OK) >= 0) {
747 log_error("Sealing key file %s exists already.", p);
752 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
753 SD_ID128_FORMAT_VAL(machine)) < 0) {
758 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
759 mpk = alloca(mpk_size);
761 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
762 seed = alloca(seed_size);
764 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
765 state = alloca(state_size);
767 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
769 log_error("Failed to open /dev/random: %m");
774 log_info("Generating seed...");
775 l = loop_read(fd, seed, seed_size, true);
776 if (l < 0 || (size_t) l != seed_size) {
777 log_error("Failed to read random seed: %s", strerror(EIO));
782 log_info("Generating key pair...");
783 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
785 log_info("Generating sealing key...");
786 FSPRG_GenState0(state, mpk, seed, seed_size);
788 assert(arg_interval > 0);
790 n = now(CLOCK_REALTIME);
793 close_nointr_nofail(fd);
794 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
796 log_error("Failed to open %s: %m", k);
801 /* Enable secure remove, exclusion from dump, synchronous
802 * writing and in-place updating */
803 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
804 log_warning("FS_IOC_GETFLAGS failed: %m");
806 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
808 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
809 log_warning("FS_IOC_SETFLAGS failed: %m");
812 memcpy(h.signature, "KSHHRHLP", 8);
813 h.machine_id = machine;
815 h.header_size = htole64(sizeof(h));
816 h.start_usec = htole64(n * arg_interval);
817 h.interval_usec = htole64(arg_interval);
818 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
819 h.fsprg_state_size = htole64(state_size);
821 l = loop_write(fd, &h, sizeof(h), false);
822 if (l < 0 || (size_t) l != sizeof(h)) {
823 log_error("Failed to write header: %s", strerror(EIO));
828 l = loop_write(fd, state, state_size, false);
829 if (l < 0 || (size_t) l != state_size) {
830 log_error("Failed to write state: %s", strerror(EIO));
835 if (link(k, p) < 0) {
836 log_error("Failed to link file: %m");
844 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
845 "the following local file. This key file is automatically updated when the\n"
846 "sealing key is advanced. It should not be used on multiple hosts.\n"
850 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
851 "at a safe location and should not be saved locally on disk.\n"
852 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
855 for (i = 0; i < seed_size; i++) {
856 if (i > 0 && i % 3 == 0)
858 printf("%02x", ((uint8_t*) seed)[i]);
861 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
864 char tsb[FORMAT_TIMESPAN_MAX], *hn;
867 ANSI_HIGHLIGHT_OFF "\n"
868 "The sealing key is automatically changed every %s.\n",
869 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
871 hn = gethostname_malloc();
874 hostname_cleanup(hn, false);
875 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
877 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
880 /* If this is not an UTF-8 system don't print any QR codes */
881 if (is_locale_utf8()) {
882 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
883 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
893 close_nointr_nofail(fd);
904 log_error("Forward-secure sealing not available.");
909 static int verify(sd_journal *j) {
916 log_show_color(true);
918 HASHMAP_FOREACH(f, j->files, i) {
920 usec_t first, validated, last;
923 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
924 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
927 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
929 /* If the key was invalid give up right-away. */
932 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
935 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
936 log_info("PASS: %s", f->path);
938 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
940 log_info("=> Validated from %s to %s, final %s entries not sealed.",
941 format_timestamp(a, sizeof(a), first),
942 format_timestamp(b, sizeof(b), validated),
943 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
945 log_info("=> No sealing yet, %s of entries not sealed.",
946 format_timespan(c, sizeof(c), last - first, 0));
948 log_info("=> No sealing yet, no entries in file.");
957 static int access_check_var_log_journal(sd_journal *j) {
958 _cleanup_strv_free_ char **g = NULL;
964 have_access = in_group("systemd-journal") > 0;
967 /* Let's enumerate all groups from the default ACL of
968 * the directory, which generally should allow access
969 * to most journal files too */
970 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
978 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
979 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
980 " turn off this notice.");
982 _cleanup_free_ char *s = NULL;
984 r = strv_extend(&g, "systemd-journal");
991 s = strv_join(g, "', '");
995 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
996 " Users in the groups '%s' can see all messages.\n"
997 " Pass -q to turn off this notice.", s);
1005 static int access_check(sd_journal *j) {
1012 if (set_isempty(j->errors)) {
1013 if (hashmap_isempty(j->files))
1014 log_notice("No journal files were found.");
1018 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1020 /* If /var/log/journal doesn't even exist,
1021 * unprivileged users have no access at all */
1022 if (access("/var/log/journal", F_OK) < 0 &&
1024 in_group("systemd-journal") <= 0) {
1025 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1026 "enabled. Users in the 'systemd-journal' group may always access messages.");
1030 /* If /var/log/journal exists, try to pring a nice
1031 notice if the user lacks access to it */
1032 if (!arg_quiet && geteuid() != 0) {
1033 r = access_check_var_log_journal(j);
1038 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1039 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1040 "group may access messages.");
1045 if (hashmap_isempty(j->files)) {
1046 log_error("No journal files were opened due to insufficient permissions.");
1051 SET_FOREACH(code, j->errors, it) {
1054 err = -PTR_TO_INT(code);
1058 log_warning("Error was encountered while opening journal files: %s",
1065 int main(int argc, char *argv[]) {
1067 _cleanup_journal_close_ sd_journal*j = NULL;
1068 bool need_seek = false;
1069 sd_id128_t previous_boot_id;
1070 bool previous_boot_id_valid = false, first_line = true;
1073 setlocale(LC_ALL, "");
1074 log_parse_environment();
1077 r = parse_argv(argc, argv);
1081 signal(SIGWINCH, columns_lines_cache_reset);
1083 if (arg_action == ACTION_NEW_ID128) {
1084 r = generate_new_id128();
1088 if (arg_action == ACTION_SETUP_KEYS) {
1093 if (arg_action == ACTION_UPDATE_CATALOG ||
1094 arg_action == ACTION_LIST_CATALOG ||
1095 arg_action == ACTION_DUMP_CATALOG) {
1097 const char* database = CATALOG_DATABASE;
1098 _cleanup_free_ char *copy = NULL;
1100 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1105 path_kill_slashes(copy);
1109 if (arg_action == ACTION_UPDATE_CATALOG) {
1110 r = catalog_update(database, arg_root, catalog_file_dirs);
1112 log_error("Failed to list catalog: %s", strerror(-r));
1114 bool oneline = arg_action == ACTION_LIST_CATALOG;
1117 r = catalog_list_items(stdout, database,
1118 oneline, argv + optind);
1120 r = catalog_list(stdout, database, oneline);
1122 log_error("Failed to list catalog: %s", strerror(-r));
1129 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1131 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1133 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1135 log_error("Failed to open %s: %s",
1136 arg_directory ? arg_directory : arg_file ? "files" : "journal",
1138 return EXIT_FAILURE;
1141 r = access_check(j);
1143 return EXIT_FAILURE;
1145 if (arg_action == ACTION_VERIFY) {
1150 if (arg_action == ACTION_PRINT_HEADER) {
1151 journal_print_header(j);
1152 return EXIT_SUCCESS;
1155 if (arg_action == ACTION_DISK_USAGE) {
1157 char sbytes[FORMAT_BYTES_MAX];
1159 r = sd_journal_get_usage(j, &bytes);
1161 return EXIT_FAILURE;
1163 printf("Journals take up %s on disk.\n",
1164 format_bytes(sbytes, sizeof(sbytes), bytes));
1165 return EXIT_SUCCESS;
1168 r = add_this_boot(j);
1170 return EXIT_FAILURE;
1174 return EXIT_FAILURE;
1177 strv_free(arg_system_units);
1178 strv_free(arg_user_units);
1181 return EXIT_FAILURE;
1183 r = add_priorities(j);
1185 return EXIT_FAILURE;
1187 r = add_matches(j, argv + optind);
1189 return EXIT_FAILURE;
1191 log_debug("Journal filter: %s", j->level0 ? journal_make_match_string(j) : "none");
1197 r = sd_journal_set_data_threshold(j, 0);
1199 log_error("Failed to unset data size threshold");
1200 return EXIT_FAILURE;
1203 r = sd_journal_query_unique(j, arg_field);
1205 log_error("Failed to query unique data objects: %s", strerror(-r));
1206 return EXIT_FAILURE;
1209 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1212 if (arg_lines >= 0 && n_shown >= arg_lines)
1215 eq = memchr(data, '=', size);
1217 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1219 printf("%.*s\n", (int) size, (const char*) data);
1224 return EXIT_SUCCESS;
1227 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1229 r = sd_journal_get_fd(j);
1231 return EXIT_FAILURE;
1235 r = sd_journal_seek_cursor(j, arg_cursor);
1237 log_error("Failed to seek to cursor: %s", strerror(-r));
1238 return EXIT_FAILURE;
1241 r = sd_journal_next(j);
1243 r = sd_journal_previous(j);
1245 } else if (arg_since_set && !arg_reverse) {
1246 r = sd_journal_seek_realtime_usec(j, arg_since);
1248 log_error("Failed to seek to date: %s", strerror(-r));
1249 return EXIT_FAILURE;
1251 r = sd_journal_next(j);
1253 } else if (arg_until_set && arg_reverse) {
1254 r = sd_journal_seek_realtime_usec(j, arg_until);
1256 log_error("Failed to seek to date: %s", strerror(-r));
1257 return EXIT_FAILURE;
1259 r = sd_journal_previous(j);
1261 } else if (arg_lines >= 0) {
1262 r = sd_journal_seek_tail(j);
1264 log_error("Failed to seek to tail: %s", strerror(-r));
1265 return EXIT_FAILURE;
1268 r = sd_journal_previous_skip(j, arg_lines);
1270 } else if (arg_reverse) {
1271 r = sd_journal_seek_tail(j);
1273 log_error("Failed to seek to tail: %s", strerror(-r));
1274 return EXIT_FAILURE;
1277 r = sd_journal_previous(j);
1280 r = sd_journal_seek_head(j);
1282 log_error("Failed to seek to head: %s", strerror(-r));
1283 return EXIT_FAILURE;
1286 r = sd_journal_next(j);
1290 log_error("Failed to iterate through journal: %s", strerror(-r));
1291 return EXIT_FAILURE;
1294 if (!arg_no_pager && !arg_follow)
1295 pager_open(arg_pager_end);
1299 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1301 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1303 log_error("Failed to get cutoff: %s", strerror(-r));
1309 printf("-- Logs begin at %s. --\n",
1310 format_timestamp(start_buf, sizeof(start_buf), start));
1312 printf("-- Logs begin at %s, end at %s. --\n",
1313 format_timestamp(start_buf, sizeof(start_buf), start),
1314 format_timestamp(end_buf, sizeof(end_buf), end));
1319 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1324 r = sd_journal_next(j);
1326 r = sd_journal_previous(j);
1328 log_error("Failed to iterate through journal: %s", strerror(-r));
1335 if (arg_until_set && !arg_reverse) {
1338 r = sd_journal_get_realtime_usec(j, &usec);
1340 log_error("Failed to determine timestamp: %s", strerror(-r));
1343 if (usec > arg_until)
1347 if (arg_since_set && arg_reverse) {
1350 r = sd_journal_get_realtime_usec(j, &usec);
1352 log_error("Failed to determine timestamp: %s", strerror(-r));
1355 if (usec < arg_since)
1361 const char *color_on = on_tty() ? ANSI_HIGHLIGHT_ON : "",
1362 *color_off = on_tty() ? ANSI_HIGHLIGHT_OFF : "";
1364 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1366 if (previous_boot_id_valid &&
1367 !sd_id128_equal(boot_id, previous_boot_id))
1368 printf("%s-- Reboot --%s\n", color_on, color_off);
1370 previous_boot_id = boot_id;
1371 previous_boot_id_valid = true;
1376 arg_all * OUTPUT_SHOW_ALL |
1377 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1378 on_tty() * OUTPUT_COLOR |
1379 arg_catalog * OUTPUT_CATALOG;
1381 r = output_journal(stdout, j, arg_output, 0, flags);
1383 if (r == -EADDRNOTAVAIL)
1385 else if (r < 0 || ferror(stdout))
1394 r = sd_journal_wait(j, (uint64_t) -1);
1396 log_error("Couldn't wait for journal event: %s", strerror(-r));
1406 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;