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;
82 static bool arg_force = false;
84 static usec_t arg_since, arg_until;
85 static bool arg_since_set = false, arg_until_set = false;
86 static char **arg_system_units = NULL;
87 static char **arg_user_units = NULL;
88 static const char *arg_field = NULL;
89 static bool arg_catalog = false;
90 static bool arg_reverse = false;
91 static int arg_journal_type = 0;
92 static const char *arg_root = NULL;
103 ACTION_UPDATE_CATALOG
104 } arg_action = ACTION_SHOW;
106 static int help(void) {
108 printf("%s [OPTIONS...] [MATCHES...]\n\n"
109 "Query the journal.\n\n"
111 " --system Show only the system journal\n"
112 " --user Show only the user journal for current user\n"
113 " --since=DATE Start showing entries newer or of the specified date\n"
114 " --until=DATE Stop showing entries older or of the specified date\n"
115 " -c --cursor=CURSOR Start showing entries from specified cursor\n"
116 " -b --this-boot Show data only from current boot\n"
117 " -k --dmesg Show kmsg log from current boot\n"
118 " -u --unit=UNIT Show data only from the specified unit\n"
119 " --user-unit=UNIT Show data only from the specified user session unit\n"
120 " -p --priority=RANGE Show only messages within the specified priority range\n"
121 " -e --pager-end Immediately jump to end of the journal in the pager\n"
122 " -f --follow Follow journal\n"
123 " -n --lines[=INTEGER] Number of journal entries to show\n"
124 " --no-tail Show all lines, even in follow mode\n"
125 " -r --reverse Show the newest entries first\n"
126 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
127 " verbose, export, json, json-pretty, json-sse, cat)\n"
128 " -x --catalog Add message explanations where available\n"
129 " -l --full Do not ellipsize fields\n"
130 " -a --all Show all fields, including long and unprintable\n"
131 " -q --quiet Don't show privilege warning\n"
132 " --no-pager Do not pipe output into a pager\n"
133 " -m --merge Show entries from all available journals\n"
134 " -D --directory=PATH Show journal files from directory\n"
135 " --file=PATH Show journal file\n"
136 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
138 " --interval=TIME Time interval for changing the FSS sealing key\n"
139 " --verify-key=KEY Specify FSS verification key\n"
142 " -h --help Show this help\n"
143 " --version Show package version\n"
144 " --new-id128 Generate a new 128 Bit ID\n"
145 " --header Show journal header information\n"
146 " --disk-usage Show total disk usage\n"
147 " -F --field=FIELD List all values a certain field takes\n"
148 " --list-catalog Show message IDs of all entries in the message catalog\n"
149 " --dump-catalog Show entries in the message catalog\n"
150 " --update-catalog Update the message catalog database\n"
152 " --setup-keys Generate new FSS key pair\n"
153 " --force Force overriding new FSS key pair with --setup-keys\n"
154 " --verify Verify journal file consistency\n"
156 , program_invocation_short_name);
161 static int parse_argv(int argc, char *argv[]) {
187 static const struct option options[] = {
188 { "help", no_argument, NULL, 'h' },
189 { "version" , no_argument, NULL, ARG_VERSION },
190 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
191 { "pager-end", no_argument, NULL, 'e' },
192 { "follow", no_argument, NULL, 'f' },
193 { "force", no_argument, NULL, ARG_FORCE },
194 { "output", required_argument, NULL, 'o' },
195 { "all", no_argument, NULL, 'a' },
196 { "full", no_argument, NULL, 'l' },
197 { "lines", optional_argument, NULL, 'n' },
198 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
199 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
200 { "quiet", no_argument, NULL, 'q' },
201 { "merge", no_argument, NULL, 'm' },
202 { "this-boot", no_argument, NULL, 'b' },
203 { "dmesg", no_argument, NULL, 'k' },
204 { "system", no_argument, NULL, ARG_SYSTEM },
205 { "user", no_argument, NULL, ARG_USER },
206 { "directory", required_argument, NULL, 'D' },
207 { "file", required_argument, NULL, ARG_FILE },
208 { "root", required_argument, NULL, ARG_ROOT },
209 { "header", no_argument, NULL, ARG_HEADER },
210 { "priority", required_argument, NULL, 'p' },
211 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
212 { "interval", required_argument, NULL, ARG_INTERVAL },
213 { "verify", no_argument, NULL, ARG_VERIFY },
214 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
215 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
216 { "cursor", required_argument, NULL, 'c' },
217 { "since", required_argument, NULL, ARG_SINCE },
218 { "until", required_argument, NULL, ARG_UNTIL },
219 { "unit", required_argument, NULL, 'u' },
220 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
221 { "field", required_argument, NULL, 'F' },
222 { "catalog", no_argument, NULL, 'x' },
223 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
224 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
225 { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
226 { "reverse", no_argument, NULL, 'r' },
235 while ((c = getopt_long(argc, argv, "hefo:aln::qmbkD:p:c:u:F:xr", options, NULL)) >= 0) {
244 puts(PACKAGE_STRING);
245 puts(SYSTEMD_FEATURES);
253 arg_pager_end = true;
265 arg_output = output_mode_from_string(optarg);
266 if (arg_output < 0) {
267 log_error("Unknown output format '%s'.", optarg);
271 if (arg_output == OUTPUT_EXPORT ||
272 arg_output == OUTPUT_JSON ||
273 arg_output == OUTPUT_JSON_PRETTY ||
274 arg_output == OUTPUT_JSON_SSE ||
275 arg_output == OUTPUT_CAT)
290 r = safe_atoi(optarg, &arg_lines);
291 if (r < 0 || arg_lines < 0) {
292 log_error("Failed to parse lines '%s'", optarg);
298 /* Hmm, no argument? Maybe the next
299 * word on the command line is
300 * supposed to be the argument? Let's
301 * see if there is one, and is
302 * parsable as a positive
306 safe_atoi(argv[optind], &n) >= 0 &&
322 arg_action = ACTION_NEW_ID128;
334 arg_this_boot = true;
338 arg_this_boot = arg_dmesg = true;
342 arg_journal_type |= SD_JOURNAL_SYSTEM;
346 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
350 arg_directory = optarg;
354 r = glob_extend(&arg_file, optarg);
356 log_error("Failed to add paths: %s", strerror(-r));
370 arg_action = ACTION_PRINT_HEADER;
374 arg_action = ACTION_VERIFY;
378 arg_action = ACTION_DISK_USAGE;
387 arg_action = ACTION_SETUP_KEYS;
392 arg_action = ACTION_VERIFY;
393 arg_verify_key = optarg;
398 r = parse_sec(optarg, &arg_interval);
399 if (r < 0 || arg_interval <= 0) {
400 log_error("Failed to parse sealing key change interval: %s", optarg);
409 log_error("Forward-secure sealing not available.");
416 dots = strstr(optarg, "..");
422 a = strndup(optarg, dots - optarg);
426 from = log_level_from_string(a);
427 to = log_level_from_string(dots + 2);
430 if (from < 0 || to < 0) {
431 log_error("Failed to parse log level range %s", optarg);
438 for (i = from; i <= to; i++)
439 arg_priorities |= 1 << i;
441 for (i = to; i <= from; i++)
442 arg_priorities |= 1 << i;
448 p = log_level_from_string(optarg);
450 log_error("Unknown log level %s", optarg);
456 for (i = 0; i <= p; i++)
457 arg_priorities |= 1 << i;
464 r = parse_timestamp(optarg, &arg_since);
466 log_error("Failed to parse timestamp: %s", optarg);
469 arg_since_set = true;
473 r = parse_timestamp(optarg, &arg_until);
475 log_error("Failed to parse timestamp: %s", optarg);
478 arg_until_set = true;
482 r = strv_extend(&arg_system_units, optarg);
488 r = strv_extend(&arg_user_units, optarg);
504 case ARG_LIST_CATALOG:
505 arg_action = ACTION_LIST_CATALOG;
508 case ARG_DUMP_CATALOG:
509 arg_action = ACTION_DUMP_CATALOG;
512 case ARG_UPDATE_CATALOG:
513 arg_action = ACTION_UPDATE_CATALOG;
521 log_error("Unknown option code %c", c);
526 if (arg_follow && !arg_no_tail && arg_lines < 0)
529 if (arg_directory && arg_file) {
530 log_error("Please specify either -D/--directory= or --file=, not both.");
534 if (arg_since_set && arg_until_set && arg_since > arg_until) {
535 log_error("--since= must be before --until=.");
539 if (arg_cursor && arg_since_set) {
540 log_error("Please specify either --since= or --cursor=, not both.");
544 if (arg_follow && arg_reverse) {
545 log_error("Please specify either --reverse= or --follow=, not both.");
552 static int generate_new_id128(void) {
557 r = sd_id128_randomize(&id);
559 log_error("Failed to generate ID: %s", strerror(-r));
563 printf("As string:\n"
564 SD_ID128_FORMAT_STR "\n\n"
566 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
568 "#define MESSAGE_XYZ SD_ID128_MAKE(",
569 SD_ID128_FORMAT_VAL(id),
570 SD_ID128_FORMAT_VAL(id));
571 for (i = 0; i < 16; i++)
572 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
573 fputs(")\n\n", stdout);
575 printf("As Python constant:\n"
577 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
578 SD_ID128_FORMAT_VAL(id));
583 static int add_matches(sd_journal *j, char **args) {
588 STRV_FOREACH(i, args) {
592 r = sd_journal_add_disjunction(j);
593 else if (path_is_absolute(*i)) {
594 _cleanup_free_ char *p, *t = NULL;
598 p = canonicalize_file_name(*i);
601 if (stat(path, &st) < 0) {
602 log_error("Couldn't stat file: %m");
606 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
607 t = strappend("_EXE=", path);
608 else if (S_ISCHR(st.st_mode))
609 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
610 else if (S_ISBLK(st.st_mode))
611 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
613 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
620 r = sd_journal_add_match(j, t, 0);
622 r = sd_journal_add_match(j, *i, 0);
625 log_error("Failed to add match '%s': %s", *i, strerror(-r));
633 static int add_this_boot(sd_journal *j) {
637 return add_match_this_boot(j);
640 static int add_dmesg(sd_journal *j) {
647 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
649 log_error("Failed to add match: %s", strerror(-r));
653 r = sd_journal_add_conjunction(j);
660 static int add_units(sd_journal *j) {
661 _cleanup_free_ char *u = NULL;
667 STRV_FOREACH(i, arg_system_units) {
668 u = unit_name_mangle(*i);
671 r = add_matches_for_unit(j, u);
674 r = sd_journal_add_disjunction(j);
679 STRV_FOREACH(i, arg_user_units) {
680 u = unit_name_mangle(*i);
684 r = add_matches_for_user_unit(j, u, getuid());
688 r = sd_journal_add_disjunction(j);
694 r = sd_journal_add_conjunction(j);
701 static int add_priorities(sd_journal *j) {
702 char match[] = "PRIORITY=0";
706 if (arg_priorities == 0xFF)
709 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
710 if (arg_priorities & (1 << i)) {
711 match[sizeof(match)-2] = '0' + i;
713 r = sd_journal_add_match(j, match, strlen(match));
715 log_error("Failed to add match: %s", strerror(-r));
720 r = sd_journal_add_conjunction(j);
727 static int setup_keys(void) {
729 size_t mpk_size, seed_size, state_size, i;
730 uint8_t *mpk, *seed, *state;
732 int fd = -1, r, attr = 0;
733 sd_id128_t machine, boot;
734 char *p = NULL, *k = NULL;
739 r = stat("/var/log/journal", &st);
740 if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
741 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
745 if (r < 0 || !S_ISDIR(st.st_mode)) {
746 log_error("%s is not a directory, must be using persistent logging for FSS.",
748 return r < 0 ? -errno : -ENOTDIR;
751 r = sd_id128_get_machine(&machine);
753 log_error("Failed to get machine ID: %s", strerror(-r));
757 r = sd_id128_get_boot(&boot);
759 log_error("Failed to get boot ID: %s", strerror(-r));
763 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
764 SD_ID128_FORMAT_VAL(machine)) < 0)
767 if (access(p, F_OK) >= 0) {
771 log_error("unlink(\"%s\") failed: %m", p);
776 log_error("Sealing key file %s exists already. (--force to recreate)", p);
782 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
783 SD_ID128_FORMAT_VAL(machine)) < 0) {
788 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
789 mpk = alloca(mpk_size);
791 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
792 seed = alloca(seed_size);
794 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
795 state = alloca(state_size);
797 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
799 log_error("Failed to open /dev/random: %m");
804 log_info("Generating seed...");
805 l = loop_read(fd, seed, seed_size, true);
806 if (l < 0 || (size_t) l != seed_size) {
807 log_error("Failed to read random seed: %s", strerror(EIO));
812 log_info("Generating key pair...");
813 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
815 log_info("Generating sealing key...");
816 FSPRG_GenState0(state, mpk, seed, seed_size);
818 assert(arg_interval > 0);
820 n = now(CLOCK_REALTIME);
823 close_nointr_nofail(fd);
824 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
826 log_error("Failed to open %s: %m", k);
831 /* Enable secure remove, exclusion from dump, synchronous
832 * writing and in-place updating */
833 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
834 log_warning("FS_IOC_GETFLAGS failed: %m");
836 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
838 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
839 log_warning("FS_IOC_SETFLAGS failed: %m");
842 memcpy(h.signature, "KSHHRHLP", 8);
843 h.machine_id = machine;
845 h.header_size = htole64(sizeof(h));
846 h.start_usec = htole64(n * arg_interval);
847 h.interval_usec = htole64(arg_interval);
848 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
849 h.fsprg_state_size = htole64(state_size);
851 l = loop_write(fd, &h, sizeof(h), false);
852 if (l < 0 || (size_t) l != sizeof(h)) {
853 log_error("Failed to write header: %s", strerror(EIO));
858 l = loop_write(fd, state, state_size, false);
859 if (l < 0 || (size_t) l != state_size) {
860 log_error("Failed to write state: %s", strerror(EIO));
865 if (link(k, p) < 0) {
866 log_error("Failed to link file: %m");
874 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
875 "the following local file. This key file is automatically updated when the\n"
876 "sealing key is advanced. It should not be used on multiple hosts.\n"
880 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
881 "at a safe location and should not be saved locally on disk.\n"
882 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
885 for (i = 0; i < seed_size; i++) {
886 if (i > 0 && i % 3 == 0)
888 printf("%02x", ((uint8_t*) seed)[i]);
891 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
894 char tsb[FORMAT_TIMESPAN_MAX], *hn;
897 ANSI_HIGHLIGHT_OFF "\n"
898 "The sealing key is automatically changed every %s.\n",
899 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
901 hn = gethostname_malloc();
904 hostname_cleanup(hn, false);
905 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
907 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
910 /* If this is not an UTF-8 system don't print any QR codes */
911 if (is_locale_utf8()) {
912 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
913 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
923 close_nointr_nofail(fd);
934 log_error("Forward-secure sealing not available.");
939 static int verify(sd_journal *j) {
946 log_show_color(true);
948 HASHMAP_FOREACH(f, j->files, i) {
950 usec_t first, validated, last;
953 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
954 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
957 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
959 /* If the key was invalid give up right-away. */
962 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
965 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
966 log_info("PASS: %s", f->path);
968 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
970 log_info("=> Validated from %s to %s, final %s entries not sealed.",
971 format_timestamp(a, sizeof(a), first),
972 format_timestamp(b, sizeof(b), validated),
973 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
975 log_info("=> No sealing yet, %s of entries not sealed.",
976 format_timespan(c, sizeof(c), last - first, 0));
978 log_info("=> No sealing yet, no entries in file.");
987 static int access_check_var_log_journal(sd_journal *j) {
988 _cleanup_strv_free_ char **g = NULL;
994 have_access = in_group("systemd-journal") > 0;
997 /* Let's enumerate all groups from the default ACL of
998 * the directory, which generally should allow access
999 * to most journal files too */
1000 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1007 if (strv_isempty(g))
1008 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1009 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1010 " turn off this notice.");
1012 _cleanup_free_ char *s = NULL;
1014 r = strv_extend(&g, "systemd-journal");
1021 s = strv_join(g, "', '");
1025 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1026 " Users in the groups '%s' can see all messages.\n"
1027 " Pass -q to turn off this notice.", s);
1035 static int access_check(sd_journal *j) {
1042 if (set_isempty(j->errors)) {
1043 if (hashmap_isempty(j->files))
1044 log_notice("No journal files were found.");
1048 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1050 /* If /var/log/journal doesn't even exist,
1051 * unprivileged users have no access at all */
1052 if (access("/var/log/journal", F_OK) < 0 &&
1054 in_group("systemd-journal") <= 0) {
1055 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1056 "enabled. Users in the 'systemd-journal' group may always access messages.");
1060 /* If /var/log/journal exists, try to pring a nice
1061 notice if the user lacks access to it */
1062 if (!arg_quiet && geteuid() != 0) {
1063 r = access_check_var_log_journal(j);
1068 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1069 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1070 "group may access messages.");
1075 if (hashmap_isempty(j->files)) {
1076 log_error("No journal files were opened due to insufficient permissions.");
1081 SET_FOREACH(code, j->errors, it) {
1084 err = -PTR_TO_INT(code);
1088 log_warning("Error was encountered while opening journal files: %s",
1095 int main(int argc, char *argv[]) {
1097 _cleanup_journal_close_ sd_journal*j = NULL;
1098 bool need_seek = false;
1099 sd_id128_t previous_boot_id;
1100 bool previous_boot_id_valid = false, first_line = true;
1103 setlocale(LC_ALL, "");
1104 log_parse_environment();
1107 r = parse_argv(argc, argv);
1111 signal(SIGWINCH, columns_lines_cache_reset);
1113 if (arg_action == ACTION_NEW_ID128) {
1114 r = generate_new_id128();
1118 if (arg_action == ACTION_SETUP_KEYS) {
1123 if (arg_action == ACTION_UPDATE_CATALOG ||
1124 arg_action == ACTION_LIST_CATALOG ||
1125 arg_action == ACTION_DUMP_CATALOG) {
1127 const char* database = CATALOG_DATABASE;
1128 _cleanup_free_ char *copy = NULL;
1130 copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1135 path_kill_slashes(copy);
1139 if (arg_action == ACTION_UPDATE_CATALOG) {
1140 r = catalog_update(database, arg_root, catalog_file_dirs);
1142 log_error("Failed to list catalog: %s", strerror(-r));
1144 bool oneline = arg_action == ACTION_LIST_CATALOG;
1147 r = catalog_list_items(stdout, database,
1148 oneline, argv + optind);
1150 r = catalog_list(stdout, database, oneline);
1152 log_error("Failed to list catalog: %s", strerror(-r));
1159 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1161 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1163 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1165 log_error("Failed to open %s: %s",
1166 arg_directory ? arg_directory : arg_file ? "files" : "journal",
1168 return EXIT_FAILURE;
1171 r = access_check(j);
1173 return EXIT_FAILURE;
1175 if (arg_action == ACTION_VERIFY) {
1180 if (arg_action == ACTION_PRINT_HEADER) {
1181 journal_print_header(j);
1182 return EXIT_SUCCESS;
1185 if (arg_action == ACTION_DISK_USAGE) {
1187 char sbytes[FORMAT_BYTES_MAX];
1189 r = sd_journal_get_usage(j, &bytes);
1191 return EXIT_FAILURE;
1193 printf("Journals take up %s on disk.\n",
1194 format_bytes(sbytes, sizeof(sbytes), bytes));
1195 return EXIT_SUCCESS;
1198 r = add_this_boot(j);
1200 return EXIT_FAILURE;
1204 return EXIT_FAILURE;
1207 strv_free(arg_system_units);
1208 strv_free(arg_user_units);
1211 return EXIT_FAILURE;
1213 r = add_priorities(j);
1215 return EXIT_FAILURE;
1217 r = add_matches(j, argv + optind);
1219 return EXIT_FAILURE;
1221 log_debug("Journal filter: %s", j->level0 ? journal_make_match_string(j) : "none");
1227 r = sd_journal_set_data_threshold(j, 0);
1229 log_error("Failed to unset data size threshold");
1230 return EXIT_FAILURE;
1233 r = sd_journal_query_unique(j, arg_field);
1235 log_error("Failed to query unique data objects: %s", strerror(-r));
1236 return EXIT_FAILURE;
1239 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1242 if (arg_lines >= 0 && n_shown >= arg_lines)
1245 eq = memchr(data, '=', size);
1247 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1249 printf("%.*s\n", (int) size, (const char*) data);
1254 return EXIT_SUCCESS;
1257 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1259 r = sd_journal_get_fd(j);
1261 return EXIT_FAILURE;
1265 r = sd_journal_seek_cursor(j, arg_cursor);
1267 log_error("Failed to seek to cursor: %s", strerror(-r));
1268 return EXIT_FAILURE;
1271 r = sd_journal_next(j);
1273 r = sd_journal_previous(j);
1275 } else if (arg_since_set && !arg_reverse) {
1276 r = sd_journal_seek_realtime_usec(j, arg_since);
1278 log_error("Failed to seek to date: %s", strerror(-r));
1279 return EXIT_FAILURE;
1281 r = sd_journal_next(j);
1283 } else if (arg_until_set && arg_reverse) {
1284 r = sd_journal_seek_realtime_usec(j, arg_until);
1286 log_error("Failed to seek to date: %s", strerror(-r));
1287 return EXIT_FAILURE;
1289 r = sd_journal_previous(j);
1291 } else if (arg_lines >= 0) {
1292 r = sd_journal_seek_tail(j);
1294 log_error("Failed to seek to tail: %s", strerror(-r));
1295 return EXIT_FAILURE;
1298 r = sd_journal_previous_skip(j, arg_lines);
1300 } else if (arg_reverse) {
1301 r = sd_journal_seek_tail(j);
1303 log_error("Failed to seek to tail: %s", strerror(-r));
1304 return EXIT_FAILURE;
1307 r = sd_journal_previous(j);
1310 r = sd_journal_seek_head(j);
1312 log_error("Failed to seek to head: %s", strerror(-r));
1313 return EXIT_FAILURE;
1316 r = sd_journal_next(j);
1320 log_error("Failed to iterate through journal: %s", strerror(-r));
1321 return EXIT_FAILURE;
1324 if (!arg_no_pager && !arg_follow)
1325 pager_open(arg_pager_end);
1329 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1331 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1333 log_error("Failed to get cutoff: %s", strerror(-r));
1339 printf("-- Logs begin at %s. --\n",
1340 format_timestamp(start_buf, sizeof(start_buf), start));
1342 printf("-- Logs begin at %s, end at %s. --\n",
1343 format_timestamp(start_buf, sizeof(start_buf), start),
1344 format_timestamp(end_buf, sizeof(end_buf), end));
1349 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1354 r = sd_journal_next(j);
1356 r = sd_journal_previous(j);
1358 log_error("Failed to iterate through journal: %s", strerror(-r));
1365 if (arg_until_set && !arg_reverse) {
1368 r = sd_journal_get_realtime_usec(j, &usec);
1370 log_error("Failed to determine timestamp: %s", strerror(-r));
1373 if (usec > arg_until)
1377 if (arg_since_set && arg_reverse) {
1380 r = sd_journal_get_realtime_usec(j, &usec);
1382 log_error("Failed to determine timestamp: %s", strerror(-r));
1385 if (usec < arg_since)
1391 const char *color_on = on_tty() ? ANSI_HIGHLIGHT_ON : "",
1392 *color_off = on_tty() ? ANSI_HIGHLIGHT_OFF : "";
1394 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1396 if (previous_boot_id_valid &&
1397 !sd_id128_equal(boot_id, previous_boot_id))
1398 printf("%s-- Reboot --%s\n", color_on, color_off);
1400 previous_boot_id = boot_id;
1401 previous_boot_id_valid = true;
1406 arg_all * OUTPUT_SHOW_ALL |
1407 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1408 on_tty() * OUTPUT_COLOR |
1409 arg_catalog * OUTPUT_CATALOG;
1411 r = output_journal(stdout, j, arg_output, 0, flags);
1413 if (r == -EADDRNOTAVAIL)
1415 else if (r < 0 || ferror(stdout))
1424 r = sd_journal_wait(j, (uint64_t) -1);
1426 log_error("Couldn't wait for journal event: %s", strerror(-r));
1436 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;