diff options
Diffstat (limited to 'src/journal/journalctl-misc.c')
-rw-r--r-- | src/journal/journalctl-misc.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/src/journal/journalctl-misc.c b/src/journal/journalctl-misc.c new file mode 100644 index 0000000000..c7a49eefea --- /dev/null +++ b/src/journal/journalctl-misc.c @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "dirent-util.h" +#include "fd-util.h" +#include "format-table.h" +#include "format-util.h" +#include "journal-internal.h" +#include "journal-verify.h" +#include "journalctl.h" +#include "journalctl-misc.h" +#include "journalctl-util.h" +#include "logs-show.h" +#include "syslog-util.h" + +int action_print_header(void) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert(arg_action == ACTION_PRINT_HEADER); + + r = acquire_journal(&j); + if (r < 0) + return r; + + journal_print_header(j); + return 0; +} + +int action_verify(void) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert(arg_action == ACTION_VERIFY); + + r = acquire_journal(&j); + if (r < 0) + return r; + + log_show_color(true); + + JournalFile *f; + ORDERED_HASHMAP_FOREACH(f, j->files) { + int k; + usec_t first = 0, validated = 0, last = 0; + +#if HAVE_GCRYPT + if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) + log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); +#endif + + k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, /* show_progress = */ !arg_quiet); + if (k == -EINVAL) + /* If the key was invalid give up right-away. */ + return k; + if (k < 0) + r = log_warning_errno(k, "FAIL: %s (%m)", f->path); + else { + char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX]; + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "PASS: %s", f->path); + + if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) { + if (validated > 0) { + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, + "=> Validated from %s to %s, final %s entries not sealed.", + format_timestamp_maybe_utc(a, sizeof(a), first), + format_timestamp_maybe_utc(b, sizeof(b), validated), + FORMAT_TIMESPAN(last > validated ? last - validated : 0, 0)); + } else if (last > 0) + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, + "=> No sealing yet, %s of entries not sealed.", + FORMAT_TIMESPAN(last - first, 0)); + else + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, + "=> No sealing yet, no entries in file."); + } + } + } + + return r; +} + +int action_disk_usage(void) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + uint64_t bytes = 0; + int r; + + assert(arg_action == ACTION_DISK_USAGE); + + r = acquire_journal(&j); + if (r < 0) + return r; + + r = sd_journal_get_usage(j, &bytes); + if (r < 0) + return log_error_errno(r, "Failed to get disk usage: %m"); + + printf("Archived and active journals take up %s in the file system.\n", FORMAT_BYTES(bytes)); + return 0; +} + +int action_list_boots(void) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + _cleanup_free_ BootId *boots = NULL; + size_t n_boots; + int r; + + assert(arg_action == ACTION_LIST_BOOTS); + + r = acquire_journal(&j); + if (r < 0) + return r; + + r = journal_get_boots(j, &boots, &n_boots); + if (r < 0) + return log_error_errno(r, "Failed to determine boots: %m"); + if (r == 0) + return 0; + + table = table_new("idx", "boot id", "first entry", "last entry"); + if (!table) + return log_oom(); + + if (arg_full) + table_set_width(table, 0); + + r = table_set_json_field_name(table, 0, "index"); + if (r < 0) + return log_error_errno(r, "Failed to set JSON field name of column 0: %m"); + + (void) table_set_sort(table, (size_t) 0); + (void) table_set_reverse(table, 0, arg_reverse); + + FOREACH_ARRAY(i, boots, n_boots) { + r = table_add_many(table, + TABLE_INT, (int)(i - boots) - (int) n_boots + 1, + TABLE_SET_ALIGN_PERCENT, 100, + TABLE_ID128, i->id, + TABLE_TIMESTAMP, i->first_usec, + TABLE_TIMESTAMP, i->last_usec); + if (r < 0) + return table_log_add_error(r); + } + + r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, !arg_quiet); + if (r < 0) + return table_log_print_error(r); + + return 0; +} + +int action_list_fields(void) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r, n_shown = 0; + + assert(arg_action == ACTION_LIST_FIELDS); + assert(arg_field); + + r = acquire_journal(&j); + if (r < 0) + return r; + + if (!journal_boot_has_effect(j)) + return 0; + + r = sd_journal_set_data_threshold(j, 0); + if (r < 0) + return log_error_errno(r, "Failed to unset data size threshold: %m"); + + r = sd_journal_query_unique(j, arg_field); + if (r < 0) + return log_error_errno(r, "Failed to query unique data objects: %m"); + + const void *data; + size_t size; + SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { + const void *eq; + + if (arg_lines >= 0 && n_shown >= arg_lines) + break; + + eq = memchr(data, '=', size); + if (eq) + printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1); + else + printf("%.*s\n", (int) size, (const char*) data); + + n_shown++; + } + + return 0; +} + +int action_list_field_names(void) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert(arg_action == ACTION_LIST_FIELD_NAMES); + + r = acquire_journal(&j); + if (r < 0) + return r; + + const char *field; + SD_JOURNAL_FOREACH_FIELD(j, field) + printf("%s\n", field); + + return 0; +} + +int action_list_namespaces(void) { + _cleanup_(table_unrefp) Table *table = NULL; + sd_id128_t machine; + char machine_id[SD_ID128_STRING_MAX]; + int r; + + assert(arg_action == ACTION_LIST_NAMESPACES); + + r = sd_id128_get_machine(&machine); + if (r < 0) + return log_error_errno(r, "Failed to get machine ID: %m"); + + sd_id128_to_string(machine, machine_id); + + table = table_new("namespace"); + if (!table) + return log_oom(); + + (void) table_set_sort(table, (size_t) 0); + + FOREACH_STRING(dir, "/var/log/journal", "/run/log/journal") { + _cleanup_free_ char *path = NULL; + _cleanup_closedir_ DIR *dirp = NULL; + + path = path_join(arg_root, dir); + if (!path) + return log_oom(); + + dirp = opendir(path); + if (!dirp) { + log_debug_errno(errno, "Failed to open directory %s, ignoring: %m", path); + continue; + } + + FOREACH_DIRENT(de, dirp, return log_error_errno(errno, "Failed to iterate through %s: %m", path)) { + char *dot; + + if (!startswith(de->d_name, machine_id)) + continue; + + dot = strchr(de->d_name, '.'); + if (!dot) + continue; + + if (!log_namespace_name_valid(dot + 1)) + continue; + + r = table_add_cell(table, NULL, TABLE_STRING, dot + 1); + if (r < 0) + return table_log_add_error(r); + } + } + + r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, !arg_quiet); + if (r < 0) + return table_log_print_error(r); + + return 0; +} |