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 int arg_priorities = 0xFF;
78 static const char *arg_verify_key = NULL;
80 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
82 static usec_t arg_since, arg_until;
83 static bool arg_since_set = false, arg_until_set = false;
84 static char **arg_system_units = NULL;
85 static char **arg_user_units = NULL;
86 static const char *arg_field = NULL;
87 static bool arg_catalog = false;
88 static bool arg_reverse = false;
89 static int arg_journal_type = 0;
90 static const char *arg_root = NULL;
101 ACTION_UPDATE_CATALOG
102 } arg_action = ACTION_SHOW;
104 static int help(void) {
106 printf("%s [OPTIONS...] [MATCHES...]\n\n"
107 "Query the journal.\n\n"
109 " --system Show only the system journal\n"
110 " --user Show only the user journal for current user\n"
111 " --since=DATE Start showing entries newer or of the specified date\n"
112 " --until=DATE Stop showing entries older or of the specified date\n"
113 " -c --cursor=CURSOR Start showing entries from specified cursor\n"
114 " -b --this-boot Show data only from current boot\n"
115 " -k --dmesg Show kmsg log from current boot\n"
116 " -u --unit=UNIT Show data only from the specified unit\n"
117 " --user-unit=UNIT Show data only from the specified user session unit\n"
118 " -p --priority=RANGE Show only messages within the specified priority range\n"
119 " -e --pager-end Immediately jump to end of the journal in the pager\n"
120 " -f --follow Follow journal\n"
121 " -n --lines[=INTEGER] Number of journal entries to show\n"
122 " --no-tail Show all lines, even in follow mode\n"
123 " -r --reverse Show the newest entries first\n"
124 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
125 " verbose, export, json, json-pretty, json-sse, cat)\n"
126 " -x --catalog Add message explanations where available\n"
127 " --full Do not ellipsize fields\n"
128 " -a --all Show all fields, including long and unprintable\n"
129 " -q --quiet Don't show privilege warning\n"
130 " --no-pager Do not pipe output into a pager\n"
131 " -m --merge Show entries from all available journals\n"
132 " -D --directory=PATH Show journal files from directory\n"
133 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
135 " --interval=TIME Time interval for changing the FSS sealing key\n"
136 " --verify-key=KEY Specify FSS verification key\n"
139 " -h --help Show this help\n"
140 " --version Show package version\n"
141 " --new-id128 Generate a new 128 Bit ID\n"
142 " --header Show journal header information\n"
143 " --disk-usage Show total disk usage\n"
144 " -F --field=FIELD List all values a certain field takes\n"
145 " --list-catalog Show message IDs of all entries in the message catalog\n"
146 " --dump-catalog Show entries in the message catalog\n"
147 " --update-catalog Update the message catalog database\n"
149 " --setup-keys Generate new FSS key pair\n"
150 " --verify Verify journal file consistency\n"
152 , program_invocation_short_name);
157 static int parse_argv(int argc, char *argv[]) {
182 static const struct option options[] = {
183 { "help", no_argument, NULL, 'h' },
184 { "version" , no_argument, NULL, ARG_VERSION },
185 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
186 { "pager-end", no_argument, NULL, 'e' },
187 { "follow", no_argument, NULL, 'f' },
188 { "output", required_argument, NULL, 'o' },
189 { "all", no_argument, NULL, 'a' },
190 { "full", no_argument, NULL, ARG_FULL },
191 { "lines", optional_argument, NULL, 'n' },
192 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
193 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
194 { "quiet", no_argument, NULL, 'q' },
195 { "merge", no_argument, NULL, 'm' },
196 { "this-boot", no_argument, NULL, 'b' },
197 { "dmesg", no_argument, NULL, 'k' },
198 { "system", no_argument, NULL, ARG_SYSTEM },
199 { "user", no_argument, NULL, ARG_USER },
200 { "directory", required_argument, NULL, 'D' },
201 { "root", required_argument, NULL, ARG_ROOT },
202 { "header", no_argument, NULL, ARG_HEADER },
203 { "priority", required_argument, NULL, 'p' },
204 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
205 { "interval", required_argument, NULL, ARG_INTERVAL },
206 { "verify", no_argument, NULL, ARG_VERIFY },
207 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
208 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
209 { "cursor", required_argument, NULL, 'c' },
210 { "since", required_argument, NULL, ARG_SINCE },
211 { "until", required_argument, NULL, ARG_UNTIL },
212 { "unit", required_argument, NULL, 'u' },
213 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
214 { "field", required_argument, NULL, 'F' },
215 { "catalog", no_argument, NULL, 'x' },
216 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
217 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
218 { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
219 { "reverse", no_argument, NULL, 'r' },
228 while ((c = getopt_long(argc, argv, "hefo:an::qmbkD:p:c:u:F:xr", options, NULL)) >= 0) {
237 puts(PACKAGE_STRING);
238 puts(SYSTEMD_FEATURES);
246 arg_pager_end = true;
258 arg_output = output_mode_from_string(optarg);
259 if (arg_output < 0) {
260 log_error("Unknown output format '%s'.", optarg);
264 if (arg_output == OUTPUT_EXPORT ||
265 arg_output == OUTPUT_JSON ||
266 arg_output == OUTPUT_JSON_PRETTY ||
267 arg_output == OUTPUT_JSON_SSE ||
268 arg_output == OUTPUT_CAT)
283 r = safe_atoi(optarg, &arg_lines);
284 if (r < 0 || arg_lines < 0) {
285 log_error("Failed to parse lines '%s'", optarg);
291 /* Hmm, no argument? Maybe the next
292 * word on the command line is
293 * supposed to be the argument? Let's
294 * see if there is one, and is
295 * parsable as a positive
299 safe_atoi(argv[optind], &n) >= 0 &&
315 arg_action = ACTION_NEW_ID128;
327 arg_this_boot = true;
331 arg_this_boot = arg_dmesg = true;
335 arg_journal_type |= SD_JOURNAL_SYSTEM;
339 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
343 arg_directory = optarg;
355 arg_action = ACTION_PRINT_HEADER;
359 arg_action = ACTION_VERIFY;
363 arg_action = ACTION_DISK_USAGE;
368 arg_action = ACTION_SETUP_KEYS;
373 arg_action = ACTION_VERIFY;
374 arg_verify_key = optarg;
379 r = parse_sec(optarg, &arg_interval);
380 if (r < 0 || arg_interval <= 0) {
381 log_error("Failed to parse sealing key change interval: %s", optarg);
389 log_error("Forward-secure sealing not available.");
396 dots = strstr(optarg, "..");
402 a = strndup(optarg, dots - optarg);
406 from = log_level_from_string(a);
407 to = log_level_from_string(dots + 2);
410 if (from < 0 || to < 0) {
411 log_error("Failed to parse log level range %s", optarg);
418 for (i = from; i <= to; i++)
419 arg_priorities |= 1 << i;
421 for (i = to; i <= from; i++)
422 arg_priorities |= 1 << i;
428 p = log_level_from_string(optarg);
430 log_error("Unknown log level %s", optarg);
436 for (i = 0; i <= p; i++)
437 arg_priorities |= 1 << i;
444 r = parse_timestamp(optarg, &arg_since);
446 log_error("Failed to parse timestamp: %s", optarg);
449 arg_since_set = true;
453 r = parse_timestamp(optarg, &arg_until);
455 log_error("Failed to parse timestamp: %s", optarg);
458 arg_until_set = true;
462 r = strv_extend(&arg_system_units, optarg);
468 r = strv_extend(&arg_user_units, optarg);
484 case ARG_LIST_CATALOG:
485 arg_action = ACTION_LIST_CATALOG;
488 case ARG_DUMP_CATALOG:
489 arg_action = ACTION_DUMP_CATALOG;
492 case ARG_UPDATE_CATALOG:
493 arg_action = ACTION_UPDATE_CATALOG;
501 log_error("Unknown option code %c", c);
506 if (arg_follow && !arg_no_tail && arg_lines < 0)
509 if (arg_since_set && arg_until_set && arg_since > arg_until) {
510 log_error("--since= must be before --until=.");
514 if (arg_cursor && arg_since_set) {
515 log_error("Please specify either --since= or --cursor=, not both.");
519 if (arg_follow && arg_reverse) {
520 log_error("Please specify either --reverse= or --follow=, not both.");
527 static int generate_new_id128(void) {
532 r = sd_id128_randomize(&id);
534 log_error("Failed to generate ID: %s", strerror(-r));
538 printf("As string:\n"
539 SD_ID128_FORMAT_STR "\n\n"
541 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
543 "#define MESSAGE_XYZ SD_ID128_MAKE(",
544 SD_ID128_FORMAT_VAL(id),
545 SD_ID128_FORMAT_VAL(id));
546 for (i = 0; i < 16; i++)
547 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
548 fputs(")\n\n", stdout);
550 printf("As Python constant:\n"
552 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
553 SD_ID128_FORMAT_VAL(id));
558 static int add_matches(sd_journal *j, char **args) {
563 STRV_FOREACH(i, args) {
567 r = sd_journal_add_disjunction(j);
568 else if (path_is_absolute(*i)) {
569 _cleanup_free_ char *p, *t = NULL;
573 p = canonicalize_file_name(*i);
576 if (stat(path, &st) < 0) {
577 log_error("Couldn't stat file: %m");
581 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
582 t = strappend("_EXE=", path);
583 else if (S_ISCHR(st.st_mode))
584 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
585 else if (S_ISBLK(st.st_mode))
586 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
588 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
595 r = sd_journal_add_match(j, t, 0);
597 r = sd_journal_add_match(j, *i, 0);
600 log_error("Failed to add match '%s': %s", *i, strerror(-r));
608 static int add_this_boot(sd_journal *j) {
612 return add_match_this_boot(j);
615 static int add_dmesg(sd_journal *j) {
622 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
624 log_error("Failed to add match: %s", strerror(-r));
628 r = sd_journal_add_conjunction(j);
635 static int add_units(sd_journal *j) {
636 _cleanup_free_ char *u = NULL;
642 STRV_FOREACH(i, arg_system_units) {
643 u = unit_name_mangle(*i);
646 r = add_matches_for_unit(j, u);
649 r = sd_journal_add_disjunction(j);
654 STRV_FOREACH(i, arg_user_units) {
655 u = unit_name_mangle(*i);
659 r = add_matches_for_user_unit(j, u, getuid());
663 r = sd_journal_add_disjunction(j);
669 r = sd_journal_add_conjunction(j);
676 static int add_priorities(sd_journal *j) {
677 char match[] = "PRIORITY=0";
681 if (arg_priorities == 0xFF)
684 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
685 if (arg_priorities & (1 << i)) {
686 match[sizeof(match)-2] = '0' + i;
688 r = sd_journal_add_match(j, match, strlen(match));
690 log_error("Failed to add match: %s", strerror(-r));
695 r = sd_journal_add_conjunction(j);
702 static int setup_keys(void) {
704 size_t mpk_size, seed_size, state_size, i;
705 uint8_t *mpk, *seed, *state;
707 int fd = -1, r, attr = 0;
708 sd_id128_t machine, boot;
709 char *p = NULL, *k = NULL;
713 r = sd_id128_get_machine(&machine);
715 log_error("Failed to get machine ID: %s", strerror(-r));
719 r = sd_id128_get_boot(&boot);
721 log_error("Failed to get boot ID: %s", strerror(-r));
725 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
726 SD_ID128_FORMAT_VAL(machine)) < 0)
729 if (access(p, F_OK) >= 0) {
730 log_error("Sealing key file %s exists already.", p);
735 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
736 SD_ID128_FORMAT_VAL(machine)) < 0) {
741 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
742 mpk = alloca(mpk_size);
744 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
745 seed = alloca(seed_size);
747 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
748 state = alloca(state_size);
750 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
752 log_error("Failed to open /dev/random: %m");
757 log_info("Generating seed...");
758 l = loop_read(fd, seed, seed_size, true);
759 if (l < 0 || (size_t) l != seed_size) {
760 log_error("Failed to read random seed: %s", strerror(EIO));
765 log_info("Generating key pair...");
766 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
768 log_info("Generating sealing key...");
769 FSPRG_GenState0(state, mpk, seed, seed_size);
771 assert(arg_interval > 0);
773 n = now(CLOCK_REALTIME);
776 close_nointr_nofail(fd);
777 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
779 log_error("Failed to open %s: %m", k);
784 /* Enable secure remove, exclusion from dump, synchronous
785 * writing and in-place updating */
786 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
787 log_warning("FS_IOC_GETFLAGS failed: %m");
789 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
791 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
792 log_warning("FS_IOC_SETFLAGS failed: %m");
795 memcpy(h.signature, "KSHHRHLP", 8);
796 h.machine_id = machine;
798 h.header_size = htole64(sizeof(h));
799 h.start_usec = htole64(n * arg_interval);
800 h.interval_usec = htole64(arg_interval);
801 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
802 h.fsprg_state_size = htole64(state_size);
804 l = loop_write(fd, &h, sizeof(h), false);
805 if (l < 0 || (size_t) l != sizeof(h)) {
806 log_error("Failed to write header: %s", strerror(EIO));
811 l = loop_write(fd, state, state_size, false);
812 if (l < 0 || (size_t) l != state_size) {
813 log_error("Failed to write state: %s", strerror(EIO));
818 if (link(k, p) < 0) {
819 log_error("Failed to link file: %m");
827 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
828 "the following local file. This key file is automatically updated when the\n"
829 "sealing key is advanced. It should not be used on multiple hosts.\n"
833 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
834 "at a safe location and should not be saved locally on disk.\n"
835 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
838 for (i = 0; i < seed_size; i++) {
839 if (i > 0 && i % 3 == 0)
841 printf("%02x", ((uint8_t*) seed)[i]);
844 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
847 char tsb[FORMAT_TIMESPAN_MAX], *hn;
850 ANSI_HIGHLIGHT_OFF "\n"
851 "The sealing key is automatically changed every %s.\n",
852 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
854 hn = gethostname_malloc();
857 hostname_cleanup(hn, false);
858 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
860 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
863 /* If this is not an UTF-8 system don't print any QR codes */
864 if (is_locale_utf8()) {
865 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
866 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
876 close_nointr_nofail(fd);
887 log_error("Forward-secure sealing not available.");
892 static int verify(sd_journal *j) {
899 log_show_color(true);
901 HASHMAP_FOREACH(f, j->files, i) {
903 usec_t first, validated, last;
906 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
907 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
910 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
912 /* If the key was invalid give up right-away. */
915 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
918 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
919 log_info("PASS: %s", f->path);
921 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
923 log_info("=> Validated from %s to %s, final %s entries not sealed.",
924 format_timestamp(a, sizeof(a), first),
925 format_timestamp(b, sizeof(b), validated),
926 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
928 log_info("=> No sealing yet, %s of entries not sealed.",
929 format_timespan(c, sizeof(c), last - first, 0));
931 log_info("=> No sealing yet, no entries in file.");
940 static int access_check_var_log_journal(sd_journal *j) {
941 _cleanup_strv_free_ char **g = NULL;
947 have_access = in_group("systemd-journal") > 0;
950 /* Let's enumerate all groups from the default ACL of
951 * the directory, which generally should allow access
952 * to most journal files too */
953 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
961 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
962 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
963 " turn off this notice.");
965 _cleanup_free_ char *s = NULL;
967 r = strv_extend(&g, "systemd-journal");
974 s = strv_join(g, "', '");
978 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
979 " Users in the groups '%s' can see all messages.\n"
980 " Pass -q to turn off this notice.", s);
988 static int access_check(sd_journal *j) {
995 if (set_isempty(j->errors)) {
996 if (hashmap_isempty(j->files))
997 log_notice("No journal files were found.");
1001 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1003 /* If /var/log/journal doesn't even exist,
1004 * unprivileged users have no access at all */
1005 if (access("/var/log/journal", F_OK) < 0 &&
1007 in_group("systemd-journal") <= 0) {
1008 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1009 "enabled. Users in the 'systemd-journal' group may always access messages.");
1013 /* If /var/log/journal exists, try to pring a nice
1014 notice if the user lacks access to it */
1015 if (!arg_quiet && geteuid() != 0) {
1016 r = access_check_var_log_journal(j);
1021 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1022 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1023 "group may access messages.");
1028 if (hashmap_isempty(j->files)) {
1029 log_error("No journal files were opened due to insufficient permissions.");
1034 SET_FOREACH(code, j->errors, it) {
1037 err = -PTR_TO_INT(code);
1041 log_warning("Error was encountered while opening journal files: %s",
1048 int main(int argc, char *argv[]) {
1050 _cleanup_journal_close_ sd_journal*j = NULL;
1051 bool need_seek = false;
1052 sd_id128_t previous_boot_id;
1053 bool previous_boot_id_valid = false, first_line = true;
1056 setlocale(LC_ALL, "");
1057 log_parse_environment();
1060 r = parse_argv(argc, argv);
1064 signal(SIGWINCH, columns_lines_cache_reset);
1066 if (arg_action == ACTION_NEW_ID128) {
1067 r = generate_new_id128();
1071 if (arg_action == ACTION_SETUP_KEYS) {
1076 if (arg_action == ACTION_UPDATE_CATALOG ||
1077 arg_action == ACTION_LIST_CATALOG ||
1078 arg_action == ACTION_DUMP_CATALOG) {
1080 const char* database = CATALOG_DATABASE;
1081 _cleanup_free_ char *copy = NULL;
1083 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1088 path_kill_slashes(copy);
1092 if (arg_action == ACTION_UPDATE_CATALOG) {
1093 r = catalog_update(database, arg_root, catalog_file_dirs);
1095 log_error("Failed to list catalog: %s", strerror(-r));
1097 bool oneline = arg_action == ACTION_LIST_CATALOG;
1100 r = catalog_list_items(stdout, database,
1101 oneline, argv + optind);
1103 r = catalog_list(stdout, database, oneline);
1105 log_error("Failed to list catalog: %s", strerror(-r));
1112 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1114 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1116 log_error("Failed to open journal: %s", strerror(-r));
1117 return EXIT_FAILURE;
1120 r = access_check(j);
1122 return EXIT_FAILURE;
1124 if (arg_action == ACTION_VERIFY) {
1129 if (arg_action == ACTION_PRINT_HEADER) {
1130 journal_print_header(j);
1131 return EXIT_SUCCESS;
1134 if (arg_action == ACTION_DISK_USAGE) {
1136 char sbytes[FORMAT_BYTES_MAX];
1138 r = sd_journal_get_usage(j, &bytes);
1140 return EXIT_FAILURE;
1142 printf("Journals take up %s on disk.\n",
1143 format_bytes(sbytes, sizeof(sbytes), bytes));
1144 return EXIT_SUCCESS;
1147 r = add_this_boot(j);
1149 return EXIT_FAILURE;
1153 return EXIT_FAILURE;
1156 strv_free(arg_system_units);
1157 strv_free(arg_user_units);
1160 return EXIT_FAILURE;
1162 r = add_priorities(j);
1164 return EXIT_FAILURE;
1166 r = add_matches(j, argv + optind);
1168 return EXIT_FAILURE;
1170 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1171 r = sd_journal_get_fd(j);
1173 return EXIT_FAILURE;
1179 r = sd_journal_set_data_threshold(j, 0);
1181 log_error("Failed to unset data size threshold");
1182 return EXIT_FAILURE;
1185 r = sd_journal_query_unique(j, arg_field);
1187 log_error("Failed to query unique data objects: %s", strerror(-r));
1188 return EXIT_FAILURE;
1191 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1194 if (arg_lines >= 0 && n_shown >= arg_lines)
1197 eq = memchr(data, '=', size);
1199 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1201 printf("%.*s\n", (int) size, (const char*) data);
1206 return EXIT_SUCCESS;
1210 r = sd_journal_seek_cursor(j, arg_cursor);
1212 log_error("Failed to seek to cursor: %s", strerror(-r));
1213 return EXIT_FAILURE;
1216 r = sd_journal_next(j);
1218 r = sd_journal_previous(j);
1220 } else if (arg_since_set && !arg_reverse) {
1221 r = sd_journal_seek_realtime_usec(j, arg_since);
1223 log_error("Failed to seek to date: %s", strerror(-r));
1224 return EXIT_FAILURE;
1226 r = sd_journal_next(j);
1228 } else if (arg_until_set && arg_reverse) {
1229 r = sd_journal_seek_realtime_usec(j, arg_until);
1231 log_error("Failed to seek to date: %s", strerror(-r));
1232 return EXIT_FAILURE;
1234 r = sd_journal_previous(j);
1236 } else if (arg_lines >= 0) {
1237 r = sd_journal_seek_tail(j);
1239 log_error("Failed to seek to tail: %s", strerror(-r));
1240 return EXIT_FAILURE;
1243 r = sd_journal_previous_skip(j, arg_lines);
1245 } else if (arg_reverse) {
1246 r = sd_journal_seek_tail(j);
1248 log_error("Failed to seek to tail: %s", strerror(-r));
1249 return EXIT_FAILURE;
1252 r = sd_journal_previous(j);
1255 r = sd_journal_seek_head(j);
1257 log_error("Failed to seek to head: %s", strerror(-r));
1258 return EXIT_FAILURE;
1261 r = sd_journal_next(j);
1265 log_error("Failed to iterate through journal: %s", strerror(-r));
1266 return EXIT_FAILURE;
1269 if (!arg_no_pager && !arg_follow)
1270 pager_open(arg_pager_end);
1274 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1276 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1278 log_error("Failed to get cutoff: %s", strerror(-r));
1284 printf("-- Logs begin at %s. --\n",
1285 format_timestamp(start_buf, sizeof(start_buf), start));
1287 printf("-- Logs begin at %s, end at %s. --\n",
1288 format_timestamp(start_buf, sizeof(start_buf), start),
1289 format_timestamp(end_buf, sizeof(end_buf), end));
1294 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1299 r = sd_journal_next(j);
1301 r = sd_journal_previous(j);
1303 log_error("Failed to iterate through journal: %s", strerror(-r));
1310 if (arg_until_set && !arg_reverse) {
1313 r = sd_journal_get_realtime_usec(j, &usec);
1315 log_error("Failed to determine timestamp: %s", strerror(-r));
1318 if (usec > arg_until)
1322 if (arg_since_set && arg_reverse) {
1325 r = sd_journal_get_realtime_usec(j, &usec);
1327 log_error("Failed to determine timestamp: %s", strerror(-r));
1330 if (usec < arg_since)
1337 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1339 if (previous_boot_id_valid &&
1340 !sd_id128_equal(boot_id, previous_boot_id))
1341 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1343 previous_boot_id = boot_id;
1344 previous_boot_id_valid = true;
1349 arg_all * OUTPUT_SHOW_ALL |
1350 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1351 on_tty() * OUTPUT_COLOR |
1352 arg_catalog * OUTPUT_CATALOG;
1354 r = output_journal(stdout, j, arg_output, 0, flags);
1356 if (r == -EADDRNOTAVAIL)
1358 else if (r < 0 || ferror(stdout))
1367 r = sd_journal_wait(j, (uint64_t) -1);
1369 log_error("Couldn't wait for journal event: %s", strerror(-r));
1379 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;