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 const char *arg_root = NULL;
100 ACTION_UPDATE_CATALOG
101 } arg_action = ACTION_SHOW;
103 static int help(void) {
105 printf("%s [OPTIONS...] [MATCHES...]\n\n"
106 "Query the journal.\n\n"
108 " --since=DATE Start showing entries newer or of the specified date\n"
109 " --until=DATE Stop showing entries older or of the specified date\n"
110 " -c --cursor=CURSOR Start showing entries from specified cursor\n"
111 " -b --this-boot Show data only from current boot\n"
112 " -k --dmesg Show kmsg log from current boot\n"
113 " -u --unit=UNIT Show data only from the specified unit\n"
114 " --user-unit=UNIT Show data only from the specified user session unit\n"
115 " -p --priority=RANGE Show only messages within the specified priority range\n"
116 " -e --pager-end Immediately jump to end of the journal in the pager\n"
117 " -f --follow Follow journal\n"
118 " -n --lines[=INTEGER] Number of journal entries to show\n"
119 " --no-tail Show all lines, even in follow mode\n"
120 " -r --reverse Show the newest entries first\n"
121 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
122 " verbose, export, json, json-pretty, json-sse, cat)\n"
123 " -x --catalog Add message explanations where available\n"
124 " --full Do not ellipsize fields\n"
125 " -a --all Show all fields, including long and unprintable\n"
126 " -q --quiet Don't show privilege warning\n"
127 " --no-pager Do not pipe output into a pager\n"
128 " -m --merge Show entries from all available journals\n"
129 " -D --directory=PATH Show journal files from directory\n"
130 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
132 " --interval=TIME Time interval for changing the FSS sealing key\n"
133 " --verify-key=KEY Specify FSS verification key\n"
136 " -h --help Show this help\n"
137 " --version Show package version\n"
138 " --new-id128 Generate a new 128 Bit ID\n"
139 " --header Show journal header information\n"
140 " --disk-usage Show total disk usage\n"
141 " -F --field=FIELD List all values a certain field takes\n"
142 " --list-catalog Show message IDs of all entries in the message catalog\n"
143 " --dump-catalog Show entries in the message catalog\n"
144 " --update-catalog Update the message catalog database\n"
146 " --setup-keys Generate new FSS key pair\n"
147 " --verify Verify journal file consistency\n"
149 , program_invocation_short_name);
154 static int parse_argv(int argc, char *argv[]) {
177 static const struct option options[] = {
178 { "help", no_argument, NULL, 'h' },
179 { "version" , no_argument, NULL, ARG_VERSION },
180 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
181 { "pager-end", no_argument, NULL, 'e' },
182 { "follow", no_argument, NULL, 'f' },
183 { "output", required_argument, NULL, 'o' },
184 { "all", no_argument, NULL, 'a' },
185 { "full", no_argument, NULL, ARG_FULL },
186 { "lines", optional_argument, NULL, 'n' },
187 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
188 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
189 { "quiet", no_argument, NULL, 'q' },
190 { "merge", no_argument, NULL, 'm' },
191 { "this-boot", no_argument, NULL, 'b' },
192 { "dmesg", no_argument, NULL, 'k' },
193 { "directory", required_argument, NULL, 'D' },
194 { "root", required_argument, NULL, ARG_ROOT },
195 { "header", no_argument, NULL, ARG_HEADER },
196 { "priority", required_argument, NULL, 'p' },
197 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
198 { "interval", required_argument, NULL, ARG_INTERVAL },
199 { "verify", no_argument, NULL, ARG_VERIFY },
200 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
201 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
202 { "cursor", required_argument, NULL, 'c' },
203 { "since", required_argument, NULL, ARG_SINCE },
204 { "until", required_argument, NULL, ARG_UNTIL },
205 { "unit", required_argument, NULL, 'u' },
206 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
207 { "field", required_argument, NULL, 'F' },
208 { "catalog", no_argument, NULL, 'x' },
209 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
210 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
211 { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
212 { "reverse", no_argument, NULL, 'r' },
221 while ((c = getopt_long(argc, argv, "hefo:an::qmbkD:p:c:u:F:xr", options, NULL)) >= 0) {
230 puts(PACKAGE_STRING);
231 puts(SYSTEMD_FEATURES);
239 arg_pager_end = true;
251 arg_output = output_mode_from_string(optarg);
252 if (arg_output < 0) {
253 log_error("Unknown output format '%s'.", optarg);
257 if (arg_output == OUTPUT_EXPORT ||
258 arg_output == OUTPUT_JSON ||
259 arg_output == OUTPUT_JSON_PRETTY ||
260 arg_output == OUTPUT_JSON_SSE ||
261 arg_output == OUTPUT_CAT)
276 r = safe_atoi(optarg, &arg_lines);
277 if (r < 0 || arg_lines < 0) {
278 log_error("Failed to parse lines '%s'", optarg);
284 /* Hmm, no argument? Maybe the next
285 * word on the command line is
286 * supposed to be the argument? Let's
287 * see if there is one, and is
288 * parsable as a positive
292 safe_atoi(argv[optind], &n) >= 0 &&
308 arg_action = ACTION_NEW_ID128;
320 arg_this_boot = true;
324 arg_this_boot = arg_dmesg = true;
328 arg_directory = optarg;
340 arg_action = ACTION_PRINT_HEADER;
344 arg_action = ACTION_VERIFY;
348 arg_action = ACTION_DISK_USAGE;
353 arg_action = ACTION_SETUP_KEYS;
358 arg_action = ACTION_VERIFY;
359 arg_verify_key = optarg;
364 r = parse_sec(optarg, &arg_interval);
365 if (r < 0 || arg_interval <= 0) {
366 log_error("Failed to parse sealing key change interval: %s", optarg);
374 log_error("Forward-secure sealing not available.");
381 dots = strstr(optarg, "..");
387 a = strndup(optarg, dots - optarg);
391 from = log_level_from_string(a);
392 to = log_level_from_string(dots + 2);
395 if (from < 0 || to < 0) {
396 log_error("Failed to parse log level range %s", optarg);
403 for (i = from; i <= to; i++)
404 arg_priorities |= 1 << i;
406 for (i = to; i <= from; i++)
407 arg_priorities |= 1 << i;
413 p = log_level_from_string(optarg);
415 log_error("Unknown log level %s", optarg);
421 for (i = 0; i <= p; i++)
422 arg_priorities |= 1 << i;
429 r = parse_timestamp(optarg, &arg_since);
431 log_error("Failed to parse timestamp: %s", optarg);
434 arg_since_set = true;
438 r = parse_timestamp(optarg, &arg_until);
440 log_error("Failed to parse timestamp: %s", optarg);
443 arg_until_set = true;
447 r = strv_extend(&arg_system_units, optarg);
453 r = strv_extend(&arg_user_units, optarg);
469 case ARG_LIST_CATALOG:
470 arg_action = ACTION_LIST_CATALOG;
473 case ARG_DUMP_CATALOG:
474 arg_action = ACTION_DUMP_CATALOG;
477 case ARG_UPDATE_CATALOG:
478 arg_action = ACTION_UPDATE_CATALOG;
486 log_error("Unknown option code %c", c);
491 if (arg_follow && !arg_no_tail && arg_lines < 0)
494 if (arg_since_set && arg_until_set && arg_since > arg_until) {
495 log_error("--since= must be before --until=.");
499 if (arg_cursor && arg_since_set) {
500 log_error("Please specify either --since= or --cursor=, not both.");
504 if (arg_follow && arg_reverse) {
505 log_error("Please specify either --reverse= or --follow=, not both.");
512 static int generate_new_id128(void) {
517 r = sd_id128_randomize(&id);
519 log_error("Failed to generate ID: %s", strerror(-r));
523 printf("As string:\n"
524 SD_ID128_FORMAT_STR "\n\n"
526 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
528 "#define MESSAGE_XYZ SD_ID128_MAKE(",
529 SD_ID128_FORMAT_VAL(id),
530 SD_ID128_FORMAT_VAL(id));
531 for (i = 0; i < 16; i++)
532 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
533 fputs(")\n\n", stdout);
535 printf("As Python constant:\n"
537 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
538 SD_ID128_FORMAT_VAL(id));
543 static int add_matches(sd_journal *j, char **args) {
548 STRV_FOREACH(i, args) {
552 r = sd_journal_add_disjunction(j);
553 else if (path_is_absolute(*i)) {
554 _cleanup_free_ char *p, *t = NULL;
558 p = canonicalize_file_name(*i);
561 if (stat(path, &st) < 0) {
562 log_error("Couldn't stat file: %m");
566 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
567 t = strappend("_EXE=", path);
568 else if (S_ISCHR(st.st_mode))
569 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
570 else if (S_ISBLK(st.st_mode))
571 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
573 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
580 r = sd_journal_add_match(j, t, 0);
582 r = sd_journal_add_match(j, *i, 0);
585 log_error("Failed to add match '%s': %s", *i, strerror(-r));
593 static int add_this_boot(sd_journal *j) {
597 return add_match_this_boot(j);
600 static int add_dmesg(sd_journal *j) {
607 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
609 log_error("Failed to add match: %s", strerror(-r));
613 r = sd_journal_add_conjunction(j);
620 static int add_units(sd_journal *j) {
621 _cleanup_free_ char *u = NULL;
627 STRV_FOREACH(i, arg_system_units) {
628 u = unit_name_mangle(*i);
631 r = add_matches_for_unit(j, u);
634 r = sd_journal_add_disjunction(j);
639 STRV_FOREACH(i, arg_user_units) {
640 u = unit_name_mangle(*i);
644 r = add_matches_for_user_unit(j, u, getuid());
648 r = sd_journal_add_disjunction(j);
654 r = sd_journal_add_conjunction(j);
661 static int add_priorities(sd_journal *j) {
662 char match[] = "PRIORITY=0";
666 if (arg_priorities == 0xFF)
669 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
670 if (arg_priorities & (1 << i)) {
671 match[sizeof(match)-2] = '0' + i;
673 r = sd_journal_add_match(j, match, strlen(match));
675 log_error("Failed to add match: %s", strerror(-r));
680 r = sd_journal_add_conjunction(j);
687 static int setup_keys(void) {
689 size_t mpk_size, seed_size, state_size, i;
690 uint8_t *mpk, *seed, *state;
692 int fd = -1, r, attr = 0;
693 sd_id128_t machine, boot;
694 char *p = NULL, *k = NULL;
698 r = sd_id128_get_machine(&machine);
700 log_error("Failed to get machine ID: %s", strerror(-r));
704 r = sd_id128_get_boot(&boot);
706 log_error("Failed to get boot ID: %s", strerror(-r));
710 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
711 SD_ID128_FORMAT_VAL(machine)) < 0)
714 if (access(p, F_OK) >= 0) {
715 log_error("Sealing key file %s exists already.", p);
720 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
721 SD_ID128_FORMAT_VAL(machine)) < 0) {
726 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
727 mpk = alloca(mpk_size);
729 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
730 seed = alloca(seed_size);
732 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
733 state = alloca(state_size);
735 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
737 log_error("Failed to open /dev/random: %m");
742 log_info("Generating seed...");
743 l = loop_read(fd, seed, seed_size, true);
744 if (l < 0 || (size_t) l != seed_size) {
745 log_error("Failed to read random seed: %s", strerror(EIO));
750 log_info("Generating key pair...");
751 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
753 log_info("Generating sealing key...");
754 FSPRG_GenState0(state, mpk, seed, seed_size);
756 assert(arg_interval > 0);
758 n = now(CLOCK_REALTIME);
761 close_nointr_nofail(fd);
762 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
764 log_error("Failed to open %s: %m", k);
769 /* Enable secure remove, exclusion from dump, synchronous
770 * writing and in-place updating */
771 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
772 log_warning("FS_IOC_GETFLAGS failed: %m");
774 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
776 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
777 log_warning("FS_IOC_SETFLAGS failed: %m");
780 memcpy(h.signature, "KSHHRHLP", 8);
781 h.machine_id = machine;
783 h.header_size = htole64(sizeof(h));
784 h.start_usec = htole64(n * arg_interval);
785 h.interval_usec = htole64(arg_interval);
786 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
787 h.fsprg_state_size = htole64(state_size);
789 l = loop_write(fd, &h, sizeof(h), false);
790 if (l < 0 || (size_t) l != sizeof(h)) {
791 log_error("Failed to write header: %s", strerror(EIO));
796 l = loop_write(fd, state, state_size, false);
797 if (l < 0 || (size_t) l != state_size) {
798 log_error("Failed to write state: %s", strerror(EIO));
803 if (link(k, p) < 0) {
804 log_error("Failed to link file: %m");
812 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
813 "the following local file. This key file is automatically updated when the\n"
814 "sealing key is advanced. It should not be used on multiple hosts.\n"
818 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
819 "at a safe location and should not be saved locally on disk.\n"
820 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
823 for (i = 0; i < seed_size; i++) {
824 if (i > 0 && i % 3 == 0)
826 printf("%02x", ((uint8_t*) seed)[i]);
829 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
832 char tsb[FORMAT_TIMESPAN_MAX], *hn;
835 ANSI_HIGHLIGHT_OFF "\n"
836 "The sealing key is automatically changed every %s.\n",
837 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
839 hn = gethostname_malloc();
842 hostname_cleanup(hn, false);
843 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
845 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
848 /* If this is not an UTF-8 system don't print any QR codes */
849 if (is_locale_utf8()) {
850 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
851 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
861 close_nointr_nofail(fd);
872 log_error("Forward-secure sealing not available.");
877 static int verify(sd_journal *j) {
884 log_show_color(true);
886 HASHMAP_FOREACH(f, j->files, i) {
888 usec_t first, validated, last;
891 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
892 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
895 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
897 /* If the key was invalid give up right-away. */
900 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
903 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
904 log_info("PASS: %s", f->path);
906 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
908 log_info("=> Validated from %s to %s, final %s entries not sealed.",
909 format_timestamp(a, sizeof(a), first),
910 format_timestamp(b, sizeof(b), validated),
911 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
913 log_info("=> No sealing yet, %s of entries not sealed.",
914 format_timespan(c, sizeof(c), last - first, 0));
916 log_info("=> No sealing yet, no entries in file.");
925 static int access_check_var_log_journal(sd_journal *j) {
926 _cleanup_strv_free_ char **g = NULL;
932 have_access = in_group("systemd-journal") > 0;
935 /* Let's enumerate all groups from the default ACL of
936 * the directory, which generally should allow access
937 * to most journal files too */
938 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
946 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
947 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
948 " turn off this notice.");
950 _cleanup_free_ char *s = NULL;
952 r = strv_extend(&g, "systemd-journal");
959 s = strv_join(g, "', '");
963 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
964 " Users in the groups '%s' can see all messages.\n"
965 " Pass -q to turn off this notice.", s);
973 static int access_check(sd_journal *j) {
980 if (set_isempty(j->errors)) {
981 if (hashmap_isempty(j->files))
982 log_notice("No journal files were found.");
986 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
988 /* If /var/log/journal doesn't even exist,
989 * unprivileged users have no access at all */
990 if (access("/var/log/journal", F_OK) < 0 &&
992 in_group("systemd-journal") <= 0) {
993 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
994 "enabled. Users in the 'systemd-journal' group may always access messages.");
998 /* If /var/log/journal exists, try to pring a nice
999 notice if the user lacks access to it */
1000 if (!arg_quiet && geteuid() != 0) {
1001 r = access_check_var_log_journal(j);
1006 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1007 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1008 "group may access messages.");
1013 if (hashmap_isempty(j->files)) {
1014 log_error("No journal files were opened due to insufficient permissions.");
1019 SET_FOREACH(code, j->errors, it) {
1022 err = -PTR_TO_INT(code);
1026 log_warning("Error was encountered while opening journal files: %s",
1033 int main(int argc, char *argv[]) {
1035 _cleanup_journal_close_ sd_journal*j = NULL;
1036 bool need_seek = false;
1037 sd_id128_t previous_boot_id;
1038 bool previous_boot_id_valid = false, first_line = true;
1041 setlocale(LC_ALL, "");
1042 log_parse_environment();
1045 r = parse_argv(argc, argv);
1049 signal(SIGWINCH, columns_lines_cache_reset);
1051 if (arg_action == ACTION_NEW_ID128) {
1052 r = generate_new_id128();
1056 if (arg_action == ACTION_SETUP_KEYS) {
1061 if (arg_action == ACTION_UPDATE_CATALOG ||
1062 arg_action == ACTION_LIST_CATALOG ||
1063 arg_action == ACTION_DUMP_CATALOG) {
1065 const char* database = CATALOG_DATABASE;
1066 _cleanup_free_ char *copy = NULL;
1068 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1073 path_kill_slashes(copy);
1077 if (arg_action == ACTION_UPDATE_CATALOG) {
1078 r = catalog_update(database, arg_root, catalog_file_dirs);
1080 log_error("Failed to list catalog: %s", strerror(-r));
1082 bool oneline = arg_action == ACTION_LIST_CATALOG;
1085 r = catalog_list_items(stdout, database,
1086 oneline, argv + optind);
1088 r = catalog_list(stdout, database, oneline);
1090 log_error("Failed to list catalog: %s", strerror(-r));
1097 r = sd_journal_open_directory(&j, arg_directory, 0);
1099 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
1101 log_error("Failed to open journal: %s", strerror(-r));
1102 return EXIT_FAILURE;
1105 r = access_check(j);
1107 return EXIT_FAILURE;
1109 if (arg_action == ACTION_VERIFY) {
1114 if (arg_action == ACTION_PRINT_HEADER) {
1115 journal_print_header(j);
1116 return EXIT_SUCCESS;
1119 if (arg_action == ACTION_DISK_USAGE) {
1121 char sbytes[FORMAT_BYTES_MAX];
1123 r = sd_journal_get_usage(j, &bytes);
1125 return EXIT_FAILURE;
1127 printf("Journals take up %s on disk.\n",
1128 format_bytes(sbytes, sizeof(sbytes), bytes));
1129 return EXIT_SUCCESS;
1132 r = add_this_boot(j);
1134 return EXIT_FAILURE;
1138 return EXIT_FAILURE;
1141 strv_free(arg_system_units);
1142 strv_free(arg_user_units);
1145 return EXIT_FAILURE;
1147 r = add_priorities(j);
1149 return EXIT_FAILURE;
1151 r = add_matches(j, argv + optind);
1153 return EXIT_FAILURE;
1155 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1156 r = sd_journal_get_fd(j);
1158 return EXIT_FAILURE;
1164 r = sd_journal_set_data_threshold(j, 0);
1166 log_error("Failed to unset data size threshold");
1167 return EXIT_FAILURE;
1170 r = sd_journal_query_unique(j, arg_field);
1172 log_error("Failed to query unique data objects: %s", strerror(-r));
1173 return EXIT_FAILURE;
1176 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1179 if (arg_lines >= 0 && n_shown >= arg_lines)
1182 eq = memchr(data, '=', size);
1184 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1186 printf("%.*s\n", (int) size, (const char*) data);
1191 return EXIT_SUCCESS;
1195 r = sd_journal_seek_cursor(j, arg_cursor);
1197 log_error("Failed to seek to cursor: %s", strerror(-r));
1198 return EXIT_FAILURE;
1201 r = sd_journal_next(j);
1203 r = sd_journal_previous(j);
1205 } else if (arg_since_set && !arg_reverse) {
1206 r = sd_journal_seek_realtime_usec(j, arg_since);
1208 log_error("Failed to seek to date: %s", strerror(-r));
1209 return EXIT_FAILURE;
1211 r = sd_journal_next(j);
1213 } else if (arg_until_set && arg_reverse) {
1214 r = sd_journal_seek_realtime_usec(j, arg_until);
1216 log_error("Failed to seek to date: %s", strerror(-r));
1217 return EXIT_FAILURE;
1219 r = sd_journal_previous(j);
1221 } else if (arg_lines >= 0) {
1222 r = sd_journal_seek_tail(j);
1224 log_error("Failed to seek to tail: %s", strerror(-r));
1225 return EXIT_FAILURE;
1228 r = sd_journal_previous_skip(j, arg_lines);
1230 } else if (arg_reverse) {
1231 r = sd_journal_seek_tail(j);
1233 log_error("Failed to seek to tail: %s", strerror(-r));
1234 return EXIT_FAILURE;
1237 r = sd_journal_previous(j);
1240 r = sd_journal_seek_head(j);
1242 log_error("Failed to seek to head: %s", strerror(-r));
1243 return EXIT_FAILURE;
1246 r = sd_journal_next(j);
1250 log_error("Failed to iterate through journal: %s", strerror(-r));
1251 return EXIT_FAILURE;
1254 if (!arg_no_pager && !arg_follow)
1255 pager_open(arg_pager_end);
1259 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1261 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1263 log_error("Failed to get cutoff: %s", strerror(-r));
1269 printf("-- Logs begin at %s. --\n",
1270 format_timestamp(start_buf, sizeof(start_buf), start));
1272 printf("-- Logs begin at %s, end at %s. --\n",
1273 format_timestamp(start_buf, sizeof(start_buf), start),
1274 format_timestamp(end_buf, sizeof(end_buf), end));
1279 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1284 r = sd_journal_next(j);
1286 r = sd_journal_previous(j);
1288 log_error("Failed to iterate through journal: %s", strerror(-r));
1295 if (arg_until_set && !arg_reverse) {
1298 r = sd_journal_get_realtime_usec(j, &usec);
1300 log_error("Failed to determine timestamp: %s", strerror(-r));
1303 if (usec > arg_until)
1307 if (arg_since_set && arg_reverse) {
1310 r = sd_journal_get_realtime_usec(j, &usec);
1312 log_error("Failed to determine timestamp: %s", strerror(-r));
1315 if (usec < arg_since)
1322 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1324 if (previous_boot_id_valid &&
1325 !sd_id128_equal(boot_id, previous_boot_id))
1326 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1328 previous_boot_id = boot_id;
1329 previous_boot_id_valid = true;
1334 arg_all * OUTPUT_SHOW_ALL |
1335 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1336 on_tty() * OUTPUT_COLOR |
1337 arg_catalog * OUTPUT_CATALOG;
1339 r = output_journal(stdout, j, arg_output, 0, flags);
1341 if (r == -EADDRNOTAVAIL)
1343 else if (r < 0 || ferror(stdout))
1352 r = sd_journal_wait(j, (uint64_t) -1);
1354 log_error("Couldn't wait for journal event: %s", strerror(-r));
1364 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;