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 " -l --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[]) {
184 static const struct option options[] = {
185 { "help", no_argument, NULL, 'h' },
186 { "version" , no_argument, NULL, ARG_VERSION },
187 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
188 { "pager-end", no_argument, NULL, 'e' },
189 { "follow", no_argument, NULL, 'f' },
190 { "output", required_argument, NULL, 'o' },
191 { "all", no_argument, NULL, 'a' },
192 { "full", no_argument, NULL, 'l' },
193 { "lines", optional_argument, NULL, 'n' },
194 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
195 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
196 { "quiet", no_argument, NULL, 'q' },
197 { "merge", no_argument, NULL, 'm' },
198 { "this-boot", no_argument, NULL, 'b' },
199 { "dmesg", no_argument, NULL, 'k' },
200 { "system", no_argument, NULL, ARG_SYSTEM },
201 { "user", no_argument, NULL, ARG_USER },
202 { "directory", required_argument, NULL, 'D' },
203 { "file", required_argument, NULL, ARG_FILE },
204 { "root", required_argument, NULL, ARG_ROOT },
205 { "header", no_argument, NULL, ARG_HEADER },
206 { "priority", required_argument, NULL, 'p' },
207 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
208 { "interval", required_argument, NULL, ARG_INTERVAL },
209 { "verify", no_argument, NULL, ARG_VERIFY },
210 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
211 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
212 { "cursor", required_argument, NULL, 'c' },
213 { "since", required_argument, NULL, ARG_SINCE },
214 { "until", required_argument, NULL, ARG_UNTIL },
215 { "unit", required_argument, NULL, 'u' },
216 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
217 { "field", required_argument, NULL, 'F' },
218 { "catalog", no_argument, NULL, 'x' },
219 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
220 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
221 { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
222 { "reverse", no_argument, NULL, 'r' },
231 while ((c = getopt_long(argc, argv, "hefo:aln::qmbkD:p:c:u:F:xr", options, NULL)) >= 0) {
240 puts(PACKAGE_STRING);
241 puts(SYSTEMD_FEATURES);
249 arg_pager_end = true;
261 arg_output = output_mode_from_string(optarg);
262 if (arg_output < 0) {
263 log_error("Unknown output format '%s'.", optarg);
267 if (arg_output == OUTPUT_EXPORT ||
268 arg_output == OUTPUT_JSON ||
269 arg_output == OUTPUT_JSON_PRETTY ||
270 arg_output == OUTPUT_JSON_SSE ||
271 arg_output == OUTPUT_CAT)
286 r = safe_atoi(optarg, &arg_lines);
287 if (r < 0 || arg_lines < 0) {
288 log_error("Failed to parse lines '%s'", optarg);
294 /* Hmm, no argument? Maybe the next
295 * word on the command line is
296 * supposed to be the argument? Let's
297 * see if there is one, and is
298 * parsable as a positive
302 safe_atoi(argv[optind], &n) >= 0 &&
318 arg_action = ACTION_NEW_ID128;
330 arg_this_boot = true;
334 arg_this_boot = arg_dmesg = true;
338 arg_journal_type |= SD_JOURNAL_SYSTEM;
342 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
346 arg_directory = optarg;
350 r = glob_extend(&arg_file, optarg);
352 log_error("Failed to add paths: %s", strerror(-r));
366 arg_action = ACTION_PRINT_HEADER;
370 arg_action = ACTION_VERIFY;
374 arg_action = ACTION_DISK_USAGE;
379 arg_action = ACTION_SETUP_KEYS;
384 arg_action = ACTION_VERIFY;
385 arg_verify_key = optarg;
390 r = parse_sec(optarg, &arg_interval);
391 if (r < 0 || arg_interval <= 0) {
392 log_error("Failed to parse sealing key change interval: %s", optarg);
400 log_error("Forward-secure sealing not available.");
407 dots = strstr(optarg, "..");
413 a = strndup(optarg, dots - optarg);
417 from = log_level_from_string(a);
418 to = log_level_from_string(dots + 2);
421 if (from < 0 || to < 0) {
422 log_error("Failed to parse log level range %s", optarg);
429 for (i = from; i <= to; i++)
430 arg_priorities |= 1 << i;
432 for (i = to; i <= from; i++)
433 arg_priorities |= 1 << i;
439 p = log_level_from_string(optarg);
441 log_error("Unknown log level %s", optarg);
447 for (i = 0; i <= p; i++)
448 arg_priorities |= 1 << i;
455 r = parse_timestamp(optarg, &arg_since);
457 log_error("Failed to parse timestamp: %s", optarg);
460 arg_since_set = true;
464 r = parse_timestamp(optarg, &arg_until);
466 log_error("Failed to parse timestamp: %s", optarg);
469 arg_until_set = true;
473 r = strv_extend(&arg_system_units, optarg);
479 r = strv_extend(&arg_user_units, optarg);
495 case ARG_LIST_CATALOG:
496 arg_action = ACTION_LIST_CATALOG;
499 case ARG_DUMP_CATALOG:
500 arg_action = ACTION_DUMP_CATALOG;
503 case ARG_UPDATE_CATALOG:
504 arg_action = ACTION_UPDATE_CATALOG;
512 log_error("Unknown option code %c", c);
517 if (arg_follow && !arg_no_tail && arg_lines < 0)
520 if (arg_directory && arg_file) {
521 log_error("Please specify either -D/--directory= or --file=, not both.");
525 if (arg_since_set && arg_until_set && arg_since > arg_until) {
526 log_error("--since= must be before --until=.");
530 if (arg_cursor && arg_since_set) {
531 log_error("Please specify either --since= or --cursor=, not both.");
535 if (arg_follow && arg_reverse) {
536 log_error("Please specify either --reverse= or --follow=, not both.");
543 static int generate_new_id128(void) {
548 r = sd_id128_randomize(&id);
550 log_error("Failed to generate ID: %s", strerror(-r));
554 printf("As string:\n"
555 SD_ID128_FORMAT_STR "\n\n"
557 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
559 "#define MESSAGE_XYZ SD_ID128_MAKE(",
560 SD_ID128_FORMAT_VAL(id),
561 SD_ID128_FORMAT_VAL(id));
562 for (i = 0; i < 16; i++)
563 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
564 fputs(")\n\n", stdout);
566 printf("As Python constant:\n"
568 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
569 SD_ID128_FORMAT_VAL(id));
574 static int add_matches(sd_journal *j, char **args) {
579 STRV_FOREACH(i, args) {
583 r = sd_journal_add_disjunction(j);
584 else if (path_is_absolute(*i)) {
585 _cleanup_free_ char *p, *t = NULL;
589 p = canonicalize_file_name(*i);
592 if (stat(path, &st) < 0) {
593 log_error("Couldn't stat file: %m");
597 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
598 t = strappend("_EXE=", path);
599 else if (S_ISCHR(st.st_mode))
600 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
601 else if (S_ISBLK(st.st_mode))
602 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
604 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
611 r = sd_journal_add_match(j, t, 0);
613 r = sd_journal_add_match(j, *i, 0);
616 log_error("Failed to add match '%s': %s", *i, strerror(-r));
624 static int add_this_boot(sd_journal *j) {
628 return add_match_this_boot(j);
631 static int add_dmesg(sd_journal *j) {
638 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
640 log_error("Failed to add match: %s", strerror(-r));
644 r = sd_journal_add_conjunction(j);
651 static int add_units(sd_journal *j) {
652 _cleanup_free_ char *u = NULL;
658 STRV_FOREACH(i, arg_system_units) {
659 u = unit_name_mangle(*i);
662 r = add_matches_for_unit(j, u);
665 r = sd_journal_add_disjunction(j);
670 STRV_FOREACH(i, arg_user_units) {
671 u = unit_name_mangle(*i);
675 r = add_matches_for_user_unit(j, u, getuid());
679 r = sd_journal_add_disjunction(j);
685 r = sd_journal_add_conjunction(j);
692 static int add_priorities(sd_journal *j) {
693 char match[] = "PRIORITY=0";
697 if (arg_priorities == 0xFF)
700 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
701 if (arg_priorities & (1 << i)) {
702 match[sizeof(match)-2] = '0' + i;
704 r = sd_journal_add_match(j, match, strlen(match));
706 log_error("Failed to add match: %s", strerror(-r));
711 r = sd_journal_add_conjunction(j);
718 static int setup_keys(void) {
720 size_t mpk_size, seed_size, state_size, i;
721 uint8_t *mpk, *seed, *state;
723 int fd = -1, r, attr = 0;
724 sd_id128_t machine, boot;
725 char *p = NULL, *k = NULL;
729 r = sd_id128_get_machine(&machine);
731 log_error("Failed to get machine ID: %s", strerror(-r));
735 r = sd_id128_get_boot(&boot);
737 log_error("Failed to get boot ID: %s", strerror(-r));
741 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
742 SD_ID128_FORMAT_VAL(machine)) < 0)
745 if (access(p, F_OK) >= 0) {
746 log_error("Sealing key file %s exists already.", p);
751 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
752 SD_ID128_FORMAT_VAL(machine)) < 0) {
757 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
758 mpk = alloca(mpk_size);
760 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
761 seed = alloca(seed_size);
763 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
764 state = alloca(state_size);
766 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
768 log_error("Failed to open /dev/random: %m");
773 log_info("Generating seed...");
774 l = loop_read(fd, seed, seed_size, true);
775 if (l < 0 || (size_t) l != seed_size) {
776 log_error("Failed to read random seed: %s", strerror(EIO));
781 log_info("Generating key pair...");
782 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
784 log_info("Generating sealing key...");
785 FSPRG_GenState0(state, mpk, seed, seed_size);
787 assert(arg_interval > 0);
789 n = now(CLOCK_REALTIME);
792 close_nointr_nofail(fd);
793 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
795 log_error("Failed to open %s: %m", k);
800 /* Enable secure remove, exclusion from dump, synchronous
801 * writing and in-place updating */
802 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
803 log_warning("FS_IOC_GETFLAGS failed: %m");
805 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
807 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
808 log_warning("FS_IOC_SETFLAGS failed: %m");
811 memcpy(h.signature, "KSHHRHLP", 8);
812 h.machine_id = machine;
814 h.header_size = htole64(sizeof(h));
815 h.start_usec = htole64(n * arg_interval);
816 h.interval_usec = htole64(arg_interval);
817 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
818 h.fsprg_state_size = htole64(state_size);
820 l = loop_write(fd, &h, sizeof(h), false);
821 if (l < 0 || (size_t) l != sizeof(h)) {
822 log_error("Failed to write header: %s", strerror(EIO));
827 l = loop_write(fd, state, state_size, false);
828 if (l < 0 || (size_t) l != state_size) {
829 log_error("Failed to write state: %s", strerror(EIO));
834 if (link(k, p) < 0) {
835 log_error("Failed to link file: %m");
843 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
844 "the following local file. This key file is automatically updated when the\n"
845 "sealing key is advanced. It should not be used on multiple hosts.\n"
849 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
850 "at a safe location and should not be saved locally on disk.\n"
851 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
854 for (i = 0; i < seed_size; i++) {
855 if (i > 0 && i % 3 == 0)
857 printf("%02x", ((uint8_t*) seed)[i]);
860 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
863 char tsb[FORMAT_TIMESPAN_MAX], *hn;
866 ANSI_HIGHLIGHT_OFF "\n"
867 "The sealing key is automatically changed every %s.\n",
868 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
870 hn = gethostname_malloc();
873 hostname_cleanup(hn, false);
874 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
876 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
879 /* If this is not an UTF-8 system don't print any QR codes */
880 if (is_locale_utf8()) {
881 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
882 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
892 close_nointr_nofail(fd);
903 log_error("Forward-secure sealing not available.");
908 static int verify(sd_journal *j) {
915 log_show_color(true);
917 HASHMAP_FOREACH(f, j->files, i) {
919 usec_t first, validated, last;
922 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
923 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
926 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
928 /* If the key was invalid give up right-away. */
931 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
934 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
935 log_info("PASS: %s", f->path);
937 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
939 log_info("=> Validated from %s to %s, final %s entries not sealed.",
940 format_timestamp(a, sizeof(a), first),
941 format_timestamp(b, sizeof(b), validated),
942 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
944 log_info("=> No sealing yet, %s of entries not sealed.",
945 format_timespan(c, sizeof(c), last - first, 0));
947 log_info("=> No sealing yet, no entries in file.");
956 static int access_check_var_log_journal(sd_journal *j) {
957 _cleanup_strv_free_ char **g = NULL;
963 have_access = in_group("systemd-journal") > 0;
966 /* Let's enumerate all groups from the default ACL of
967 * the directory, which generally should allow access
968 * to most journal files too */
969 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
977 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
978 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
979 " turn off this notice.");
981 _cleanup_free_ char *s = NULL;
983 r = strv_extend(&g, "systemd-journal");
990 s = strv_join(g, "', '");
994 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
995 " Users in the groups '%s' can see all messages.\n"
996 " Pass -q to turn off this notice.", s);
1004 static int access_check(sd_journal *j) {
1011 if (set_isempty(j->errors)) {
1012 if (hashmap_isempty(j->files))
1013 log_notice("No journal files were found.");
1017 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1019 /* If /var/log/journal doesn't even exist,
1020 * unprivileged users have no access at all */
1021 if (access("/var/log/journal", F_OK) < 0 &&
1023 in_group("systemd-journal") <= 0) {
1024 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1025 "enabled. Users in the 'systemd-journal' group may always access messages.");
1029 /* If /var/log/journal exists, try to pring a nice
1030 notice if the user lacks access to it */
1031 if (!arg_quiet && geteuid() != 0) {
1032 r = access_check_var_log_journal(j);
1037 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1038 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1039 "group may access messages.");
1044 if (hashmap_isempty(j->files)) {
1045 log_error("No journal files were opened due to insufficient permissions.");
1050 SET_FOREACH(code, j->errors, it) {
1053 err = -PTR_TO_INT(code);
1057 log_warning("Error was encountered while opening journal files: %s",
1064 int main(int argc, char *argv[]) {
1066 _cleanup_journal_close_ sd_journal*j = NULL;
1067 bool need_seek = false;
1068 sd_id128_t previous_boot_id;
1069 bool previous_boot_id_valid = false, first_line = true;
1072 setlocale(LC_ALL, "");
1073 log_parse_environment();
1076 r = parse_argv(argc, argv);
1080 signal(SIGWINCH, columns_lines_cache_reset);
1082 if (arg_action == ACTION_NEW_ID128) {
1083 r = generate_new_id128();
1087 if (arg_action == ACTION_SETUP_KEYS) {
1092 if (arg_action == ACTION_UPDATE_CATALOG ||
1093 arg_action == ACTION_LIST_CATALOG ||
1094 arg_action == ACTION_DUMP_CATALOG) {
1096 const char* database = CATALOG_DATABASE;
1097 _cleanup_free_ char *copy = NULL;
1099 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1104 path_kill_slashes(copy);
1108 if (arg_action == ACTION_UPDATE_CATALOG) {
1109 r = catalog_update(database, arg_root, catalog_file_dirs);
1111 log_error("Failed to list catalog: %s", strerror(-r));
1113 bool oneline = arg_action == ACTION_LIST_CATALOG;
1116 r = catalog_list_items(stdout, database,
1117 oneline, argv + optind);
1119 r = catalog_list(stdout, database, oneline);
1121 log_error("Failed to list catalog: %s", strerror(-r));
1128 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1130 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1132 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1134 log_error("Failed to open %s: %s",
1135 arg_directory ? arg_directory : arg_file ? "files" : "journal",
1137 return EXIT_FAILURE;
1140 r = access_check(j);
1142 return EXIT_FAILURE;
1144 if (arg_action == ACTION_VERIFY) {
1149 if (arg_action == ACTION_PRINT_HEADER) {
1150 journal_print_header(j);
1151 return EXIT_SUCCESS;
1154 if (arg_action == ACTION_DISK_USAGE) {
1156 char sbytes[FORMAT_BYTES_MAX];
1158 r = sd_journal_get_usage(j, &bytes);
1160 return EXIT_FAILURE;
1162 printf("Journals take up %s on disk.\n",
1163 format_bytes(sbytes, sizeof(sbytes), bytes));
1164 return EXIT_SUCCESS;
1167 r = add_this_boot(j);
1169 return EXIT_FAILURE;
1173 return EXIT_FAILURE;
1176 strv_free(arg_system_units);
1177 strv_free(arg_user_units);
1180 return EXIT_FAILURE;
1182 r = add_priorities(j);
1184 return EXIT_FAILURE;
1186 r = add_matches(j, argv + optind);
1188 return EXIT_FAILURE;
1190 log_debug("Journal filter: %s", j->level0 ? journal_make_match_string(j) : "none");
1196 r = sd_journal_set_data_threshold(j, 0);
1198 log_error("Failed to unset data size threshold");
1199 return EXIT_FAILURE;
1202 r = sd_journal_query_unique(j, arg_field);
1204 log_error("Failed to query unique data objects: %s", strerror(-r));
1205 return EXIT_FAILURE;
1208 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1211 if (arg_lines >= 0 && n_shown >= arg_lines)
1214 eq = memchr(data, '=', size);
1216 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1218 printf("%.*s\n", (int) size, (const char*) data);
1223 return EXIT_SUCCESS;
1226 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1228 r = sd_journal_get_fd(j);
1230 return EXIT_FAILURE;
1234 r = sd_journal_seek_cursor(j, arg_cursor);
1236 log_error("Failed to seek to cursor: %s", strerror(-r));
1237 return EXIT_FAILURE;
1240 r = sd_journal_next(j);
1242 r = sd_journal_previous(j);
1244 } else if (arg_since_set && !arg_reverse) {
1245 r = sd_journal_seek_realtime_usec(j, arg_since);
1247 log_error("Failed to seek to date: %s", strerror(-r));
1248 return EXIT_FAILURE;
1250 r = sd_journal_next(j);
1252 } else if (arg_until_set && arg_reverse) {
1253 r = sd_journal_seek_realtime_usec(j, arg_until);
1255 log_error("Failed to seek to date: %s", strerror(-r));
1256 return EXIT_FAILURE;
1258 r = sd_journal_previous(j);
1260 } else if (arg_lines >= 0) {
1261 r = sd_journal_seek_tail(j);
1263 log_error("Failed to seek to tail: %s", strerror(-r));
1264 return EXIT_FAILURE;
1267 r = sd_journal_previous_skip(j, arg_lines);
1269 } else if (arg_reverse) {
1270 r = sd_journal_seek_tail(j);
1272 log_error("Failed to seek to tail: %s", strerror(-r));
1273 return EXIT_FAILURE;
1276 r = sd_journal_previous(j);
1279 r = sd_journal_seek_head(j);
1281 log_error("Failed to seek to head: %s", strerror(-r));
1282 return EXIT_FAILURE;
1285 r = sd_journal_next(j);
1289 log_error("Failed to iterate through journal: %s", strerror(-r));
1290 return EXIT_FAILURE;
1293 if (!arg_no_pager && !arg_follow)
1294 pager_open(arg_pager_end);
1298 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1300 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1302 log_error("Failed to get cutoff: %s", strerror(-r));
1308 printf("-- Logs begin at %s. --\n",
1309 format_timestamp(start_buf, sizeof(start_buf), start));
1311 printf("-- Logs begin at %s, end at %s. --\n",
1312 format_timestamp(start_buf, sizeof(start_buf), start),
1313 format_timestamp(end_buf, sizeof(end_buf), end));
1318 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1323 r = sd_journal_next(j);
1325 r = sd_journal_previous(j);
1327 log_error("Failed to iterate through journal: %s", strerror(-r));
1334 if (arg_until_set && !arg_reverse) {
1337 r = sd_journal_get_realtime_usec(j, &usec);
1339 log_error("Failed to determine timestamp: %s", strerror(-r));
1342 if (usec > arg_until)
1346 if (arg_since_set && arg_reverse) {
1349 r = sd_journal_get_realtime_usec(j, &usec);
1351 log_error("Failed to determine timestamp: %s", strerror(-r));
1354 if (usec < arg_since)
1360 const char *color_on = on_tty() ? ANSI_HIGHLIGHT_ON : "",
1361 *color_off = on_tty() ? ANSI_HIGHLIGHT_OFF : "";
1363 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1365 if (previous_boot_id_valid &&
1366 !sd_id128_equal(boot_id, previous_boot_id))
1367 printf("%s-- Reboot --%s\n", color_on, color_off);
1369 previous_boot_id = boot_id;
1370 previous_boot_id_valid = true;
1375 arg_all * OUTPUT_SHOW_ALL |
1376 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1377 on_tty() * OUTPUT_COLOR |
1378 arg_catalog * OUTPUT_CATALOG;
1380 r = output_journal(stdout, j, arg_output, 0, flags);
1382 if (r == -EADDRNOTAVAIL)
1384 else if (r < 0 || ferror(stdout))
1393 r = sd_journal_wait(j, (uint64_t) -1);
1395 log_error("Couldn't wait for journal event: %s", strerror(-r));
1405 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;