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 const char *arg_cursor = NULL;
75 static const char *arg_directory = NULL;
76 static int arg_priorities = 0xFF;
77 static const char *arg_verify_key = NULL;
79 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
81 static usec_t arg_since, arg_until;
82 static bool arg_since_set = false, arg_until_set = false;
83 static char **arg_system_units = NULL;
84 static char **arg_user_units = NULL;
85 static const char *arg_field = NULL;
86 static bool arg_catalog = false;
87 static bool arg_reverse = false;
88 static const char *arg_root = NULL;
100 } arg_action = ACTION_SHOW;
102 static int help(void) {
104 printf("%s [OPTIONS...] [MATCHES...]\n\n"
105 "Query the journal.\n\n"
107 " --since=DATE Start showing entries newer or of the specified date\n"
108 " --until=DATE Stop showing entries older or of the specified date\n"
109 " -c --cursor=CURSOR Start showing entries from specified cursor\n"
110 " -b --this-boot Show data only from current boot\n"
111 " -u --unit=UNIT Show data only from the specified unit\n"
112 " --user-unit=UNIT Show data only from the specified user session unit\n"
113 " -p --priority=RANGE Show only messages within the specified priority range\n"
114 " -e --pager-end Immediately jump to end of the journal in the pager\n"
115 " -f --follow Follow journal\n"
116 " -n --lines[=INTEGER] Number of journal entries to show\n"
117 " --no-tail Show all lines, even in follow mode\n"
118 " -r --reverse Show the newest entries first\n"
119 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
120 " verbose, export, json, json-pretty, json-sse, cat)\n"
121 " -x --catalog Add message explanations where available\n"
122 " --full Do not ellipsize fields\n"
123 " -a --all Show all fields, including long and unprintable\n"
124 " -q --quiet Don't show privilege warning\n"
125 " --no-pager Do not pipe output into a pager\n"
126 " -m --merge Show entries from all available journals\n"
127 " -D --directory=PATH Show journal files from directory\n"
128 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
130 " --interval=TIME Time interval for changing the FSS sealing key\n"
131 " --verify-key=KEY Specify FSS verification key\n"
134 " -h --help Show this help\n"
135 " --version Show package version\n"
136 " --new-id128 Generate a new 128 Bit ID\n"
137 " --header Show journal header information\n"
138 " --disk-usage Show total disk usage\n"
139 " -F --field=FIELD List all values a certain field takes\n"
140 " --list-catalog Show message IDs of all entries in the message catalog\n"
141 " --dump-catalog Show entries in the message catalog\n"
142 " --update-catalog Update the message catalog database\n"
144 " --setup-keys Generate new FSS key pair\n"
145 " --verify Verify journal file consistency\n"
147 , program_invocation_short_name);
152 static int parse_argv(int argc, char *argv[]) {
175 static const struct option options[] = {
176 { "help", no_argument, NULL, 'h' },
177 { "version" , no_argument, NULL, ARG_VERSION },
178 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
179 { "pager-end", no_argument, NULL, 'e' },
180 { "follow", no_argument, NULL, 'f' },
181 { "output", required_argument, NULL, 'o' },
182 { "all", no_argument, NULL, 'a' },
183 { "full", no_argument, NULL, ARG_FULL },
184 { "lines", optional_argument, NULL, 'n' },
185 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
186 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
187 { "quiet", no_argument, NULL, 'q' },
188 { "merge", no_argument, NULL, 'm' },
189 { "this-boot", no_argument, NULL, 'b' },
190 { "directory", required_argument, NULL, 'D' },
191 { "root", required_argument, NULL, ARG_ROOT },
192 { "header", no_argument, NULL, ARG_HEADER },
193 { "priority", required_argument, NULL, 'p' },
194 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
195 { "interval", required_argument, NULL, ARG_INTERVAL },
196 { "verify", no_argument, NULL, ARG_VERIFY },
197 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
198 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
199 { "cursor", required_argument, NULL, 'c' },
200 { "since", required_argument, NULL, ARG_SINCE },
201 { "until", required_argument, NULL, ARG_UNTIL },
202 { "unit", required_argument, NULL, 'u' },
203 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
204 { "field", required_argument, NULL, 'F' },
205 { "catalog", no_argument, NULL, 'x' },
206 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
207 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
208 { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
209 { "reverse", no_argument, NULL, 'r' },
218 while ((c = getopt_long(argc, argv, "hefo:an::qmbD:p:c:u:F:xr", options, NULL)) >= 0) {
227 puts(PACKAGE_STRING);
228 puts(SYSTEMD_FEATURES);
236 arg_pager_end = true;
248 arg_output = output_mode_from_string(optarg);
249 if (arg_output < 0) {
250 log_error("Unknown output format '%s'.", optarg);
254 if (arg_output == OUTPUT_EXPORT ||
255 arg_output == OUTPUT_JSON ||
256 arg_output == OUTPUT_JSON_PRETTY ||
257 arg_output == OUTPUT_JSON_SSE ||
258 arg_output == OUTPUT_CAT)
273 r = safe_atoi(optarg, &arg_lines);
274 if (r < 0 || arg_lines < 0) {
275 log_error("Failed to parse lines '%s'", optarg);
281 /* Hmm, no argument? Maybe the next
282 * word on the command line is
283 * supposed to be the argument? Let's
284 * see if there is one, and is
285 * parsable as a positive
289 safe_atoi(argv[optind], &n) >= 0 &&
305 arg_action = ACTION_NEW_ID128;
317 arg_this_boot = true;
321 arg_directory = optarg;
333 arg_action = ACTION_PRINT_HEADER;
337 arg_action = ACTION_VERIFY;
341 arg_action = ACTION_DISK_USAGE;
346 arg_action = ACTION_SETUP_KEYS;
351 arg_action = ACTION_VERIFY;
352 arg_verify_key = optarg;
357 r = parse_sec(optarg, &arg_interval);
358 if (r < 0 || arg_interval <= 0) {
359 log_error("Failed to parse sealing key change interval: %s", optarg);
367 log_error("Forward-secure sealing not available.");
374 dots = strstr(optarg, "..");
380 a = strndup(optarg, dots - optarg);
384 from = log_level_from_string(a);
385 to = log_level_from_string(dots + 2);
388 if (from < 0 || to < 0) {
389 log_error("Failed to parse log level range %s", optarg);
396 for (i = from; i <= to; i++)
397 arg_priorities |= 1 << i;
399 for (i = to; i <= from; i++)
400 arg_priorities |= 1 << i;
406 p = log_level_from_string(optarg);
408 log_error("Unknown log level %s", optarg);
414 for (i = 0; i <= p; i++)
415 arg_priorities |= 1 << i;
422 r = parse_timestamp(optarg, &arg_since);
424 log_error("Failed to parse timestamp: %s", optarg);
427 arg_since_set = true;
431 r = parse_timestamp(optarg, &arg_until);
433 log_error("Failed to parse timestamp: %s", optarg);
436 arg_until_set = true;
440 r = strv_extend(&arg_system_units, optarg);
446 r = strv_extend(&arg_user_units, optarg);
462 case ARG_LIST_CATALOG:
463 arg_action = ACTION_LIST_CATALOG;
466 case ARG_DUMP_CATALOG:
467 arg_action = ACTION_DUMP_CATALOG;
470 case ARG_UPDATE_CATALOG:
471 arg_action = ACTION_UPDATE_CATALOG;
479 log_error("Unknown option code %c", c);
484 if (arg_follow && !arg_no_tail && arg_lines < 0)
487 if (arg_since_set && arg_until_set && arg_since > arg_until) {
488 log_error("--since= must be before --until=.");
492 if (arg_cursor && arg_since_set) {
493 log_error("Please specify either --since= or --cursor=, not both.");
497 if (arg_follow && arg_reverse) {
498 log_error("Please specify either --reverse= or --follow=, not both.");
505 static int generate_new_id128(void) {
510 r = sd_id128_randomize(&id);
512 log_error("Failed to generate ID: %s", strerror(-r));
516 printf("As string:\n"
517 SD_ID128_FORMAT_STR "\n\n"
519 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
521 "#define MESSAGE_XYZ SD_ID128_MAKE(",
522 SD_ID128_FORMAT_VAL(id),
523 SD_ID128_FORMAT_VAL(id));
524 for (i = 0; i < 16; i++)
525 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
526 fputs(")\n\n", stdout);
528 printf("As Python constant:\n"
530 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
531 SD_ID128_FORMAT_VAL(id));
536 static int add_matches(sd_journal *j, char **args) {
541 STRV_FOREACH(i, args) {
545 r = sd_journal_add_disjunction(j);
546 else if (path_is_absolute(*i)) {
547 _cleanup_free_ char *p, *t = NULL;
551 p = canonicalize_file_name(*i);
554 if (stat(path, &st) < 0) {
555 log_error("Couldn't stat file: %m");
559 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
560 t = strappend("_EXE=", path);
561 else if (S_ISCHR(st.st_mode))
562 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
563 else if (S_ISBLK(st.st_mode))
564 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
566 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
573 r = sd_journal_add_match(j, t, 0);
575 r = sd_journal_add_match(j, *i, 0);
578 log_error("Failed to add match '%s': %s", *i, strerror(-r));
586 static int add_this_boot(sd_journal *j) {
587 char match[9+32+1] = "_BOOT_ID=";
596 r = sd_id128_get_boot(&boot_id);
598 log_error("Failed to get boot id: %s", strerror(-r));
602 sd_id128_to_string(boot_id, match + 9);
603 r = sd_journal_add_match(j, match, strlen(match));
605 log_error("Failed to add match: %s", strerror(-r));
609 r = sd_journal_add_conjunction(j);
616 static int add_units(sd_journal *j) {
617 _cleanup_free_ char *u = NULL;
623 STRV_FOREACH(i, arg_system_units) {
624 u = unit_name_mangle(*i);
627 r = add_matches_for_unit(j, u);
630 r = sd_journal_add_disjunction(j);
635 STRV_FOREACH(i, arg_user_units) {
636 u = unit_name_mangle(*i);
640 r = add_matches_for_user_unit(j, u, getuid());
644 r = sd_journal_add_disjunction(j);
650 r = sd_journal_add_conjunction(j);
657 static int add_priorities(sd_journal *j) {
658 char match[] = "PRIORITY=0";
662 if (arg_priorities == 0xFF)
665 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
666 if (arg_priorities & (1 << i)) {
667 match[sizeof(match)-2] = '0' + i;
669 r = sd_journal_add_match(j, match, strlen(match));
671 log_error("Failed to add match: %s", strerror(-r));
676 r = sd_journal_add_conjunction(j);
683 static int setup_keys(void) {
685 size_t mpk_size, seed_size, state_size, i;
686 uint8_t *mpk, *seed, *state;
688 int fd = -1, r, attr = 0;
689 sd_id128_t machine, boot;
690 char *p = NULL, *k = NULL;
694 r = sd_id128_get_machine(&machine);
696 log_error("Failed to get machine ID: %s", strerror(-r));
700 r = sd_id128_get_boot(&boot);
702 log_error("Failed to get boot ID: %s", strerror(-r));
706 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
707 SD_ID128_FORMAT_VAL(machine)) < 0)
710 if (access(p, F_OK) >= 0) {
711 log_error("Sealing key file %s exists already.", p);
716 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
717 SD_ID128_FORMAT_VAL(machine)) < 0) {
722 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
723 mpk = alloca(mpk_size);
725 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
726 seed = alloca(seed_size);
728 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
729 state = alloca(state_size);
731 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
733 log_error("Failed to open /dev/random: %m");
738 log_info("Generating seed...");
739 l = loop_read(fd, seed, seed_size, true);
740 if (l < 0 || (size_t) l != seed_size) {
741 log_error("Failed to read random seed: %s", strerror(EIO));
746 log_info("Generating key pair...");
747 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
749 log_info("Generating sealing key...");
750 FSPRG_GenState0(state, mpk, seed, seed_size);
752 assert(arg_interval > 0);
754 n = now(CLOCK_REALTIME);
757 close_nointr_nofail(fd);
758 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
760 log_error("Failed to open %s: %m", k);
765 /* Enable secure remove, exclusion from dump, synchronous
766 * writing and in-place updating */
767 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
768 log_warning("FS_IOC_GETFLAGS failed: %m");
770 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
772 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
773 log_warning("FS_IOC_SETFLAGS failed: %m");
776 memcpy(h.signature, "KSHHRHLP", 8);
777 h.machine_id = machine;
779 h.header_size = htole64(sizeof(h));
780 h.start_usec = htole64(n * arg_interval);
781 h.interval_usec = htole64(arg_interval);
782 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
783 h.fsprg_state_size = htole64(state_size);
785 l = loop_write(fd, &h, sizeof(h), false);
786 if (l < 0 || (size_t) l != sizeof(h)) {
787 log_error("Failed to write header: %s", strerror(EIO));
792 l = loop_write(fd, state, state_size, false);
793 if (l < 0 || (size_t) l != state_size) {
794 log_error("Failed to write state: %s", strerror(EIO));
799 if (link(k, p) < 0) {
800 log_error("Failed to link file: %m");
808 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
809 "the following local file. This key file is automatically updated when the\n"
810 "sealing key is advanced. It should not be used on multiple hosts.\n"
814 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
815 "at a safe location and should not be saved locally on disk.\n"
816 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
819 for (i = 0; i < seed_size; i++) {
820 if (i > 0 && i % 3 == 0)
822 printf("%02x", ((uint8_t*) seed)[i]);
825 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
828 char tsb[FORMAT_TIMESPAN_MAX], *hn;
831 ANSI_HIGHLIGHT_OFF "\n"
832 "The sealing key is automatically changed every %s.\n",
833 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
835 hn = gethostname_malloc();
838 hostname_cleanup(hn);
839 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
841 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
844 /* If this is not an UTF-8 system don't print any QR codes */
845 if (is_locale_utf8()) {
846 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
847 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
857 close_nointr_nofail(fd);
868 log_error("Forward-secure sealing not available.");
873 static int verify(sd_journal *j) {
880 log_show_color(true);
882 HASHMAP_FOREACH(f, j->files, i) {
884 usec_t first, validated, last;
887 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
888 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
891 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
893 /* If the key was invalid give up right-away. */
896 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
899 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
900 log_info("PASS: %s", f->path);
902 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
904 log_info("=> Validated from %s to %s, final %s entries not sealed.",
905 format_timestamp(a, sizeof(a), first),
906 format_timestamp(b, sizeof(b), validated),
907 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
909 log_info("=> No sealing yet, %s of entries not sealed.",
910 format_timespan(c, sizeof(c), last - first, 0));
912 log_info("=> No sealing yet, no entries in file.");
921 static int access_check_var_log_journal(sd_journal *j) {
922 _cleanup_strv_free_ char **g = NULL;
928 have_access = in_group("systemd-journal") > 0;
931 /* Let's enumerate all groups from the default ACL of
932 * the directory, which generally should allow access
933 * to most journal files too */
934 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
942 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
943 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
944 " turn off this notice.");
946 _cleanup_free_ char *s = NULL;
948 r = strv_extend(&g, "systemd-journal");
955 s = strv_join(g, "', '");
959 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
960 " Users in the groups '%s' can see all messages.\n"
961 " Pass -q to turn off this notice.", s);
969 static int access_check(sd_journal *j) {
976 if (set_isempty(j->errors)) {
977 if (hashmap_isempty(j->files))
978 log_notice("No journal files were found.");
982 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
984 /* If /var/log/journal doesn't even exist,
985 * unprivileged users have no access at all */
986 if (access("/var/log/journal", F_OK) < 0 &&
988 in_group("systemd-journal") <= 0) {
989 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
990 "enabled. Users in the 'systemd-journal' group may always access messages.");
994 /* If /var/log/journal exists, try to pring a nice
995 notice if the user lacks access to it */
996 if (!arg_quiet && geteuid() != 0) {
997 r = access_check_var_log_journal(j);
1002 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1003 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1004 "group may access messages.");
1009 if (hashmap_isempty(j->files)) {
1010 log_error("No journal files were opened due to insufficient permissions.");
1015 SET_FOREACH(code, j->errors, it) {
1018 err = -PTR_TO_INT(code);
1022 log_warning("Error was encountered while opening journal files: %s",
1029 int main(int argc, char *argv[]) {
1031 _cleanup_journal_close_ sd_journal*j = NULL;
1032 bool need_seek = false;
1033 sd_id128_t previous_boot_id;
1034 bool previous_boot_id_valid = false, first_line = true;
1037 setlocale(LC_ALL, "");
1038 log_parse_environment();
1041 r = parse_argv(argc, argv);
1045 signal(SIGWINCH, columns_lines_cache_reset);
1047 if (arg_action == ACTION_NEW_ID128) {
1048 r = generate_new_id128();
1052 if (arg_action == ACTION_SETUP_KEYS) {
1057 if (arg_action == ACTION_UPDATE_CATALOG ||
1058 arg_action == ACTION_LIST_CATALOG ||
1059 arg_action == ACTION_DUMP_CATALOG) {
1061 const char* database = CATALOG_DATABASE;
1062 _cleanup_free_ char *copy = NULL;
1064 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1069 path_kill_slashes(copy);
1073 if (arg_action == ACTION_UPDATE_CATALOG) {
1074 r = catalog_update(database, arg_root, catalog_file_dirs);
1076 log_error("Failed to list catalog: %s", strerror(-r));
1078 bool oneline = arg_action == ACTION_LIST_CATALOG;
1081 r = catalog_list_items(stdout, database,
1082 oneline, argv + optind);
1084 r = catalog_list(stdout, database, oneline);
1086 log_error("Failed to list catalog: %s", strerror(-r));
1093 r = sd_journal_open_directory(&j, arg_directory, 0);
1095 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
1097 log_error("Failed to open journal: %s", strerror(-r));
1098 return EXIT_FAILURE;
1101 r = access_check(j);
1103 return EXIT_FAILURE;
1105 if (arg_action == ACTION_VERIFY) {
1110 if (arg_action == ACTION_PRINT_HEADER) {
1111 journal_print_header(j);
1112 return EXIT_SUCCESS;
1115 if (arg_action == ACTION_DISK_USAGE) {
1117 char sbytes[FORMAT_BYTES_MAX];
1119 r = sd_journal_get_usage(j, &bytes);
1121 return EXIT_FAILURE;
1123 printf("Journals take up %s on disk.\n",
1124 format_bytes(sbytes, sizeof(sbytes), bytes));
1125 return EXIT_SUCCESS;
1128 r = add_this_boot(j);
1130 return EXIT_FAILURE;
1133 strv_free(arg_system_units);
1134 strv_free(arg_user_units);
1137 return EXIT_FAILURE;
1139 r = add_priorities(j);
1141 return EXIT_FAILURE;
1143 r = add_matches(j, argv + optind);
1145 return EXIT_FAILURE;
1147 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1148 r = sd_journal_get_fd(j);
1150 return EXIT_FAILURE;
1156 r = sd_journal_set_data_threshold(j, 0);
1158 log_error("Failed to unset data size threshold");
1159 return EXIT_FAILURE;
1162 r = sd_journal_query_unique(j, arg_field);
1164 log_error("Failed to query unique data objects: %s", strerror(-r));
1165 return EXIT_FAILURE;
1168 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1171 if (arg_lines >= 0 && n_shown >= arg_lines)
1174 eq = memchr(data, '=', size);
1176 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1178 printf("%.*s\n", (int) size, (const char*) data);
1183 return EXIT_SUCCESS;
1187 r = sd_journal_seek_cursor(j, arg_cursor);
1189 log_error("Failed to seek to cursor: %s", strerror(-r));
1190 return EXIT_FAILURE;
1193 r = sd_journal_next(j);
1195 r = sd_journal_previous(j);
1197 } else if (arg_since_set && !arg_reverse) {
1198 r = sd_journal_seek_realtime_usec(j, arg_since);
1200 log_error("Failed to seek to date: %s", strerror(-r));
1201 return EXIT_FAILURE;
1203 r = sd_journal_next(j);
1205 } else if (arg_until_set && arg_reverse) {
1206 r = sd_journal_seek_realtime_usec(j, arg_until);
1208 log_error("Failed to seek to date: %s", strerror(-r));
1209 return EXIT_FAILURE;
1211 r = sd_journal_previous(j);
1213 } else if (arg_lines >= 0) {
1214 r = sd_journal_seek_tail(j);
1216 log_error("Failed to seek to tail: %s", strerror(-r));
1217 return EXIT_FAILURE;
1220 r = sd_journal_previous_skip(j, arg_lines);
1222 } else if (arg_reverse) {
1223 r = sd_journal_seek_tail(j);
1225 log_error("Failed to seek to tail: %s", strerror(-r));
1226 return EXIT_FAILURE;
1229 r = sd_journal_previous(j);
1232 r = sd_journal_seek_head(j);
1234 log_error("Failed to seek to head: %s", strerror(-r));
1235 return EXIT_FAILURE;
1238 r = sd_journal_next(j);
1242 log_error("Failed to iterate through journal: %s", strerror(-r));
1243 return EXIT_FAILURE;
1246 if (!arg_no_pager && !arg_follow)
1247 pager_open(arg_pager_end);
1251 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1253 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1255 log_error("Failed to get cutoff: %s", strerror(-r));
1261 printf("-- Logs begin at %s. --\n",
1262 format_timestamp(start_buf, sizeof(start_buf), start));
1264 printf("-- Logs begin at %s, end at %s. --\n",
1265 format_timestamp(start_buf, sizeof(start_buf), start),
1266 format_timestamp(end_buf, sizeof(end_buf), end));
1271 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1276 r = sd_journal_next(j);
1278 r = sd_journal_previous(j);
1280 log_error("Failed to iterate through journal: %s", strerror(-r));
1288 if (arg_until_set && !arg_reverse) {
1291 r = sd_journal_get_realtime_usec(j, &usec);
1293 log_error("Failed to determine timestamp: %s", strerror(-r));
1296 if (usec > arg_until)
1300 if (arg_since_set && arg_reverse) {
1303 r = sd_journal_get_realtime_usec(j, &usec);
1305 log_error("Failed to determine timestamp: %s", strerror(-r));
1308 if (usec < arg_since)
1315 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1317 if (previous_boot_id_valid &&
1318 !sd_id128_equal(boot_id, previous_boot_id))
1319 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1321 previous_boot_id = boot_id;
1322 previous_boot_id_valid = true;
1327 arg_all * OUTPUT_SHOW_ALL |
1328 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1329 on_tty() * OUTPUT_COLOR |
1330 arg_catalog * OUTPUT_CATALOG;
1332 r = output_journal(stdout, j, arg_output, 0, flags);
1333 if (r < 0 || ferror(stdout))
1343 r = sd_journal_wait(j, (uint64_t) -1);
1345 log_error("Couldn't wait for journal event: %s", strerror(-r));
1355 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;