diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/mkdir.c | 2 | ||||
-rw-r--r-- | src/basic/time-util.h | 2 | ||||
-rw-r--r-- | src/core/service.c | 4 | ||||
-rw-r--r-- | src/core/unit.c | 27 | ||||
-rw-r--r-- | src/journal/journalctl-filter.c | 53 | ||||
-rw-r--r-- | src/journal/journalctl-misc.c | 31 | ||||
-rw-r--r-- | src/journal/journalctl-util.c | 48 | ||||
-rw-r--r-- | src/journal/journalctl-util.h | 1 | ||||
-rw-r--r-- | src/journal/journalctl.c | 35 | ||||
-rw-r--r-- | src/libsystemd/sd-journal/test-journal-interleaving.c | 63 | ||||
-rw-r--r-- | src/login/loginctl.c | 18 | ||||
-rw-r--r-- | src/machine/machinectl.c | 9 | ||||
-rw-r--r-- | src/partition/repart.c | 2 | ||||
-rw-r--r-- | src/shared/logs-show.c | 135 | ||||
-rw-r--r-- | src/shared/logs-show.h | 14 | ||||
-rw-r--r-- | src/systemctl/systemctl-show.c | 3 |
16 files changed, 267 insertions, 180 deletions
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index 20329e04c2..f87de0a2bf 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -259,7 +259,7 @@ int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mod struct timespec tspec; timespec_store(&tspec, ts); - if (futimens(dfd, (const struct timespec[2]) { { .tv_nsec = UTIME_OMIT }, tspec }) < 0) + if (futimens(dfd, (const struct timespec[2]) { TIMESPEC_OMIT, tspec }) < 0) return -errno; if (futimens(nfd, (const struct timespec[2]) { tspec, tspec }) < 0) diff --git a/src/basic/time-util.h b/src/basic/time-util.h index b28ab8242f..f273770233 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -75,6 +75,8 @@ typedef enum TimestampStyle { #define DUAL_TIMESTAMP_INFINITY ((dual_timestamp) { USEC_INFINITY, USEC_INFINITY }) #define TRIPLE_TIMESTAMP_NULL ((triple_timestamp) {}) +#define TIMESPEC_OMIT ((const struct timespec) { .tv_nsec = UTIME_OMIT }) + usec_t now(clockid_t clock); nsec_t now_nsec(clockid_t clock); diff --git a/src/core/service.c b/src/core/service.c index 9c30067e92..3fb3cae844 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2441,11 +2441,9 @@ static void service_enter_start(Service *s) { return service_set_state(s, SERVICE_START); default: - ; + assert_not_reached(); } - assert_not_reached(); - fail: service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); } diff --git a/src/core/unit.c b/src/core/unit.c index 4b290934fc..0b2460cada 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1311,27 +1311,26 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { * is run first. */ if (c->log_namespace) { - FOREACH_STRING(s, "systemd-journald", "systemd-journald-varlink") { - _cleanup_free_ char *socket_unit = NULL; + static const struct { + const char *template; + UnitType type; + } deps[] = { + { "systemd-journald", UNIT_SOCKET, }, + { "systemd-journald-varlink", UNIT_SOCKET, }, + { "systemd-journald-sync", UNIT_SERVICE, }, + }; + + FOREACH_ELEMENT(i, deps) { + _cleanup_free_ char *unit = NULL; - r = unit_name_build_from_type(s, c->log_namespace, UNIT_SOCKET, &socket_unit); + r = unit_name_build_from_type(i->template, c->log_namespace, i->type, &unit); if (r < 0) return r; - r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, socket_unit, true, UNIT_DEPENDENCY_FILE); + r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, unit, true, UNIT_DEPENDENCY_FILE); if (r < 0) return r; } - - _cleanup_free_ char *sync_unit = NULL; - - r = unit_name_build_from_type("systemd-journald-sync", c->log_namespace, UNIT_SERVICE, &sync_unit); - if (r < 0) - return r; - - r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, sync_unit, true, UNIT_DEPENDENCY_FILE); - if (r < 0) - return r; } else { r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, true, UNIT_DEPENDENCY_FILE); if (r < 0) diff --git a/src/journal/journalctl-filter.c b/src/journal/journalctl-filter.c index 1fdde5eb37..f9eb9f8c58 100644 --- a/src/journal/journalctl-filter.c +++ b/src/journal/journalctl-filter.c @@ -9,6 +9,7 @@ #include "journal-internal.h" #include "journalctl.h" #include "journalctl-filter.h" +#include "journalctl-util.h" #include "logs-show.h" #include "missing_sched.h" #include "nulstr-util.h" @@ -23,42 +24,13 @@ static int add_boot(sd_journal *j) { if (!arg_boot) return 0; - /* Take a shortcut and use the current boot_id, which we can do very quickly. - * We can do this only when we logs are coming from the current machine, - * so take the slow path if log location is specified. */ - if (arg_boot_offset == 0 && sd_id128_is_null(arg_boot_id) && - !arg_directory && !arg_file && !arg_root) - return add_match_this_boot(j, arg_machine); - - if (sd_id128_is_null(arg_boot_id)) { - r = journal_find_boot_by_offset(j, arg_boot_offset, &arg_boot_id); - if (r < 0) - return log_error_errno(r, "Failed to find journal entry from the specified boot offset (%+i): %m", - arg_boot_offset); - if (r == 0) - return log_error_errno(SYNTHETIC_ERRNO(ENODATA), - "No journal boot entry found from the specified boot offset (%+i).", - arg_boot_offset); - } else { - r = journal_find_boot_by_id(j, arg_boot_id); - if (r < 0) - return log_error_errno(r, "Failed to find journal entry from the specified boot ID (%s): %m", - SD_ID128_TO_STRING(arg_boot_id)); - if (r == 0) - return log_error_errno(SYNTHETIC_ERRNO(ENODATA), - "No journal boot entry found from the specified boot ID (%s).", - SD_ID128_TO_STRING(arg_boot_id)); - } + assert(!sd_id128_is_null(arg_boot_id)); r = add_match_boot_id(j, arg_boot_id); if (r < 0) - return log_error_errno(r, "Failed to add match: %m"); - - r = sd_journal_add_conjunction(j); - if (r < 0) - return log_error_errno(r, "Failed to add conjunction: %m"); + return r; - return 0; + return sd_journal_add_conjunction(j); } static int add_dmesg(sd_journal *j) { @@ -208,7 +180,7 @@ static int add_units(sd_journal *j) { if (r < 0) return r; } else { - r = add_matches_for_user_unit(j, u, getuid()); + r = add_matches_for_user_unit(j, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); @@ -227,7 +199,7 @@ static int add_units(sd_journal *j) { return r; SET_FOREACH(u, units) { - r = add_matches_for_user_unit(j, u, getuid()); + r = add_matches_for_user_unit(j, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); @@ -457,12 +429,19 @@ int add_filters(sd_journal *j, char **matches) { assert(j); - /* add_boot() must be called first! - * It may need to seek the journal to find parent boot IDs. */ - r = add_boot(j); + /* First, search boot ID, as that may set and flush matches and seek journal. */ + r = journal_acquire_boot(j); if (r < 0) return r; + /* Clear unexpected matches for safety. */ + sd_journal_flush_matches(j); + + /* Then, add filters in the below. */ + r = add_boot(j); + if (r < 0) + return log_error_errno(r, "Failed to add filter for boot: %m"); + r = add_dmesg(j); if (r < 0) return log_error_errno(r, "Failed to add filter for dmesg: %m"); diff --git a/src/journal/journalctl-misc.c b/src/journal/journalctl-misc.c index 47eb72575a..8ca6ea2143 100644 --- a/src/journal/journalctl-misc.c +++ b/src/journal/journalctl-misc.c @@ -111,11 +111,16 @@ int action_list_boots(void) { if (r < 0) return r; - r = journal_get_boots(j, &boots, &n_boots); + r = journal_get_boots( + j, + /* advance_older = */ arg_lines_needs_seek_end(), + /* max_ids = */ arg_lines >= 0 ? (size_t) arg_lines : SIZE_MAX, + &boots, &n_boots); if (r < 0) return log_error_errno(r, "Failed to determine boots: %m"); if (r == 0) - return 0; + return log_full_errno(arg_quiet ? LOG_DEBUG : LOG_ERR, SYNTHETIC_ERRNO(ENODATA), + "No boot found."); table = table_new("idx", "boot id", "first entry", "last entry"); if (!table) @@ -131,13 +136,25 @@ int action_list_boots(void) { (void) table_set_sort(table, (size_t) 0); (void) table_set_reverse(table, 0, arg_reverse); - FOREACH_ARRAY(i, boots, n_boots) { + for (int i = 0; i < (int) n_boots; i++) { + int index; + + if (arg_lines_needs_seek_end()) + /* With --lines=N, we only know the negative index, and the older ID is located earlier. */ + index = -i; + else if (arg_lines >= 0) + /* With --lines=+N, we only know the positive index, and the newer ID is located earlier. */ + index = i + 1; + else + /* Otherwise, show negative index. Note, in this case, newer ID is located earlier. */ + index = i + 1 - (int) n_boots; + r = table_add_many(table, - TABLE_INT, (int)(i - boots) - (int) n_boots + 1, + TABLE_INT, index, TABLE_SET_ALIGN_PERCENT, 100, - TABLE_ID128, i->id, - TABLE_TIMESTAMP, i->first_usec, - TABLE_TIMESTAMP, i->last_usec); + TABLE_ID128, boots[i].id, + TABLE_TIMESTAMP, boots[i].first_usec, + TABLE_TIMESTAMP, boots[i].last_usec); if (r < 0) return table_log_add_error(r); } diff --git a/src/journal/journalctl-util.c b/src/journal/journalctl-util.c index 575488bee1..32cdaf8381 100644 --- a/src/journal/journalctl-util.c +++ b/src/journal/journalctl-util.c @@ -2,9 +2,11 @@ #include <unistd.h> +#include "id128-util.h" #include "journal-util.h" #include "journalctl.h" #include "journalctl-util.h" +#include "logs-show.h" #include "rlimit-util.h" #include "sigbus.h" #include "terminal-util.h" @@ -70,3 +72,49 @@ bool journal_boot_has_effect(sd_journal *j) { return true; } + +int journal_acquire_boot(sd_journal *j) { + int r; + + assert(j); + + if (!arg_boot) { + /* Clear relevant field for safety. */ + arg_boot_id = SD_ID128_NULL; + arg_boot_offset = 0; + return 0; + } + + /* Take a shortcut and use the current boot_id, which we can do very quickly. + * We can do this only when the logs are coming from the current machine, + * so take the slow path if log location is specified. */ + if (arg_boot_offset == 0 && sd_id128_is_null(arg_boot_id) && + !arg_directory && !arg_file && !arg_file_stdin && !arg_root) { + r = id128_get_boot_for_machine(arg_machine, &arg_boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get boot ID%s%s: %m", + isempty(arg_machine) ? "" : " of container ", strempty(arg_machine)); + } else { + sd_id128_t boot_id; + + r = journal_find_boot(j, arg_boot_id, arg_boot_offset, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to find journal entry from the specified boot (%s%+i): %m", + sd_id128_is_null(arg_boot_id) ? "" : SD_ID128_TO_STRING(arg_boot_id), + arg_boot_offset); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(ENODATA), + "No journal boot entry found from the specified boot (%s%+i).", + sd_id128_is_null(arg_boot_id) ? "" : SD_ID128_TO_STRING(arg_boot_id), + arg_boot_offset); + + log_debug("Found boot %s for %s%+i", + SD_ID128_TO_STRING(boot_id), + sd_id128_is_null(arg_boot_id) ? "" : SD_ID128_TO_STRING(arg_boot_id), + arg_boot_offset); + + arg_boot_id = boot_id; + } + + return 1; +} diff --git a/src/journal/journalctl-util.h b/src/journal/journalctl-util.h index 38f634f828..ea3e56838d 100644 --- a/src/journal/journalctl-util.h +++ b/src/journal/journalctl-util.h @@ -8,3 +8,4 @@ char* format_timestamp_maybe_utc(char *buf, size_t l, usec_t t); int acquire_journal(sd_journal **ret); bool journal_boot_has_effect(sd_journal *j); +int journal_acquire_boot(sd_journal *j); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index f634d33a97..45173a6813 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -104,15 +104,21 @@ STATIC_DESTRUCTOR_REGISTER(arg_output_fields, set_freep); STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern, pattern_freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); -static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) { +static int parse_id_descriptor(const char *x, sd_id128_t *ret_id, int *ret_offset) { sd_id128_t id = SD_ID128_NULL; int off = 0, r; + assert(x); + assert(ret_id); + assert(ret_offset); + if (streq(x, "all")) { - *boot_id = SD_ID128_NULL; - *offset = 0; + *ret_id = SD_ID128_NULL; + *ret_offset = 0; return 0; - } else if (strlen(x) >= SD_ID128_STRING_MAX - 1) { + } + + if (strlen(x) >= SD_ID128_STRING_MAX - 1) { char *t; t = strndupa_safe(x, SD_ID128_STRING_MAX - 1); @@ -134,12 +140,8 @@ static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset return r; } - if (boot_id) - *boot_id = id; - - if (offset) - *offset = off; - + *ret_id = id; + *ret_offset = off; return 1; } @@ -517,19 +519,16 @@ static int parse_argv(int argc, char *argv[]) { arg_boot_offset = 0; if (optarg) { - r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset); + r = parse_id_descriptor(optarg, &arg_boot_id, &arg_boot_offset); if (r < 0) return log_error_errno(r, "Failed to parse boot descriptor '%s'", optarg); arg_boot = r; - /* Hmm, no argument? Maybe the next - * word on the command line is - * supposed to be the argument? Let's - * see if there is one and is parsable - * as a boot descriptor... */ } else if (optind < argc) { - r = parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset); + /* Hmm, no argument? Maybe the next word on the command line is supposed to be the + * argument? Let's see if there is one and is parsable as a boot descriptor... */ + r = parse_id_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset); if (r >= 0) { arg_boot = r; optind++; @@ -958,7 +957,7 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --reverse or --follow, not both."); - if (arg_lines >= 0 && arg_lines_oldest && (arg_reverse || arg_follow)) + if (arg_action == ACTION_SHOW && arg_lines >= 0 && arg_lines_oldest && (arg_reverse || arg_follow)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--lines=+N is unsupported when --reverse or --follow is specified."); diff --git a/src/libsystemd/sd-journal/test-journal-interleaving.c b/src/libsystemd/sd-journal/test-journal-interleaving.c index ed1918d103..d98b3ce8cb 100644 --- a/src/libsystemd/sd-journal/test-journal-interleaving.c +++ b/src/libsystemd/sd-journal/test-journal-interleaving.c @@ -459,7 +459,7 @@ TEST(skip) { static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) { char t[] = "/var/tmp/journal-boot-id-XXXXXX"; - sd_journal *j; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; _cleanup_free_ BootId *boots = NULL; size_t n_boots; @@ -468,27 +468,58 @@ static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) { setup(); assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE)); - assert_se(journal_get_boots(j, &boots, &n_boots) >= 0); + assert_se(journal_get_boots( + j, + /* advance_older = */ false, /* max_ids = */ SIZE_MAX, + &boots, &n_boots) >= 0); assert_se(boots); assert_se(n_boots == n_boots_expected); - sd_journal_close(j); - FOREACH_ARRAY(b, boots, n_boots) { - assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE)); - assert_se(journal_find_boot_by_id(j, b->id) == 1); - sd_journal_close(j); + for (size_t i = 0; i < n_boots; i++) { + sd_id128_t id; + + /* positive offset */ + assert_se(journal_find_boot(j, SD_ID128_NULL, (int) (i + 1), &id) == 1); + assert_se(sd_id128_equal(id, boots[i].id)); + + /* negative offset */ + assert_se(journal_find_boot(j, SD_ID128_NULL, (int) (i + 1) - (int) n_boots, &id) == 1); + assert_se(sd_id128_equal(id, boots[i].id)); + + for (size_t k = 0; k < n_boots; k++) { + int offset = (int) k - (int) i; + + /* relative offset */ + assert_se(journal_find_boot(j, boots[i].id, offset, &id) == 1); + assert_se(sd_id128_equal(id, boots[k].id)); + } } - for (int i = - (int) n_boots + 1; i <= (int) n_boots; i++) { - sd_id128_t id; + for (size_t i = 0; i <= n_boots_expected + 1; i++) { + _cleanup_free_ BootId *boots_limited = NULL; + size_t n_boots_limited; + + assert_se(journal_get_boots( + j, + /* advance_older = */ false, /* max_ids = */ i, + &boots_limited, &n_boots_limited) >= 0); + assert_se(boots_limited || i == 0); + assert_se(n_boots_limited == MIN(i, n_boots_expected)); + assert_se(memcmp_safe(boots, boots_limited, n_boots_limited * sizeof(BootId)) == 0); + } - assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE)); - assert_se(journal_find_boot_by_offset(j, i, &id) == 1); - if (i <= 0) - assert_se(sd_id128_equal(id, boots[n_boots + i - 1].id)); - else - assert_se(sd_id128_equal(id, boots[i - 1].id)); - sd_journal_close(j); + for (size_t i = 0; i <= n_boots_expected + 1; i++) { + _cleanup_free_ BootId *boots_limited = NULL; + size_t n_boots_limited; + + assert_se(journal_get_boots( + j, + /* advance_older = */ true, /* max_ids = */ i, + &boots_limited, &n_boots_limited) >= 0); + assert_se(boots_limited || i == 0); + assert_se(n_boots_limited == MIN(i, n_boots_expected)); + for (size_t k = 0; k < n_boots_limited; k++) + assert_se(memcmp(&boots[n_boots - k - 1], &boots_limited[k], sizeof(BootId)) == 0); } test_done(t); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 8236dc2dc8..cf3bff437a 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -733,16 +733,15 @@ static int print_session_status_info(sd_bus *bus, const char *path) { show_journal_by_unit( stdout, i.scope, - NULL, + /* namespace = */ NULL, arg_output, - 0, + /* n_columns = */ 0, i.timestamp.monotonic, arg_lines, - 0, get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, - true, - NULL); + /* system_unit = */ true, + /* ellipsized = */ NULL); } return 0; @@ -839,16 +838,15 @@ static int print_user_status_info(sd_bus *bus, const char *path) { show_journal_by_unit( stdout, i.slice, - NULL, + /* namespace = */ NULL, arg_output, - 0, + /* n_columns = */ 0, i.timestamp.monotonic, arg_lines, - 0, get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, - true, - NULL); + /* system_unit = */ true, + /* ellipsized = */ NULL); } return 0; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 42b7fef720..1b63e6d203 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -605,16 +605,15 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { show_journal_by_unit( stdout, i->unit, - NULL, + /* namespace = */ NULL, arg_output, - 0, + /* n_columns = */ 0, i->timestamp.monotonic, arg_lines, - 0, get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, - true, - NULL); + /* system_unit = */ true, + /* ellipsized = */ NULL); } } diff --git a/src/partition/repart.c b/src/partition/repart.c index 4196576daa..7f7b68f9ff 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -4936,7 +4936,7 @@ static int do_copy_files(Context *context, Partition *p, const char *root) { struct timespec tspec; timespec_store(&tspec, ts); - if (futimens(pfd, (const struct timespec[2]) { { .tv_nsec = UTIME_OMIT }, tspec }) < 0) + if (futimens(pfd, (const struct timespec[2]) { TIMESPEC_OMIT, tspec }) < 0) return -errno; } } diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index d5b131a187..c71c868889 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -1620,7 +1620,8 @@ int add_matches_for_unit(sd_journal *j, const char *unit) { return r; } -int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) { +int add_matches_for_user_unit(sd_journal *j, const char *unit) { + uid_t uid = getuid(); int r; assert(j); @@ -1687,7 +1688,7 @@ int add_match_this_boot(sd_journal *j, const char *machine) { r = id128_get_boot_for_machine(machine, &boot_id); if (r < 0) return log_error_errno(r, "Failed to get boot ID%s%s: %m", - isempty(machine) ? "" : " of container ", machine); + isempty(machine) ? "" : " of container ", strempty(machine)); r = add_match_boot_id(j, boot_id); if (r < 0) @@ -1708,7 +1709,6 @@ int show_journal_by_unit( unsigned n_columns, usec_t not_before, unsigned how_many, - uid_t uid, OutputFlags flags, int journal_open_flags, bool system_unit, @@ -1734,7 +1734,7 @@ int show_journal_by_unit( if (system_unit) r = add_matches_for_unit(j, unit); else - r = add_matches_for_user_unit(j, unit, uid); + r = add_matches_for_user_unit(j, unit); if (r < 0) return log_error_errno(r, "Failed to add unit matches: %m"); @@ -1790,6 +1790,7 @@ static int discover_next_boot( if (r < 0) return r; if (r == 0) { + sd_journal_flush_matches(j); *ret = (BootId) {}; return 0; /* End of journal, yay. */ } @@ -1840,7 +1841,7 @@ static int discover_next_boot( goto try_again; } - r = sd_journal_get_realtime_usec(j, &boot.first_usec); + r = sd_journal_get_realtime_usec(j, advance_older ? &boot.last_usec : &boot.first_usec); if (r < 0) return r; @@ -1862,7 +1863,7 @@ static int discover_next_boot( goto try_again; } - r = sd_journal_get_realtime_usec(j, &boot.last_usec); + r = sd_journal_get_realtime_usec(j, advance_older ? &boot.first_usec : &boot.last_usec); if (r < 0) return r; @@ -1908,37 +1909,9 @@ static int discover_next_boot( } } -int journal_find_boot_by_id(sd_journal *j, sd_id128_t boot_id) { - int r; - - assert(j); - assert(!sd_id128_is_null(boot_id)); - - sd_journal_flush_matches(j); - - r = add_match_boot_id(j, boot_id); - if (r < 0) - return r; - - r = sd_journal_seek_head(j); /* seek to oldest */ - if (r < 0) - return r; - - r = sd_journal_next(j); /* read the oldest entry */ - if (r < 0) - return r; - - /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID. - * After flushing the matches, one more invocation of _previous() will hence place us at the - * following entry, which must then have an older boot ID */ - - sd_journal_flush_matches(j); - return r > 0; -} - -int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret) { +int journal_find_boot(sd_journal *j, sd_id128_t boot_id, int offset, sd_id128_t *ret) { bool advance_older; - int r; + int r, offset_start; assert(j); assert(ret); @@ -1947,21 +1920,52 @@ int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret) { * (chronological) first boot in the journal. */ advance_older = offset <= 0; - if (advance_older) - r = sd_journal_seek_tail(j); /* seek to newest */ - else - r = sd_journal_seek_head(j); /* seek to oldest */ - if (r < 0) - return r; + sd_journal_flush_matches(j); - /* No sd_journal_next()/_previous() here. - * - * At this point the read pointer is positioned after the newest/before the oldest entry in the whole - * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest - * entry we have. */ + if (!sd_id128_is_null(boot_id)) { + r = add_match_boot_id(j, boot_id); + if (r < 0) + return r; - sd_id128_t boot_id = SD_ID128_NULL; - for (int off = !advance_older; ; off += advance_older ? -1 : 1) { + if (advance_older) + r = sd_journal_seek_head(j); /* seek to oldest */ + else + r = sd_journal_seek_tail(j); /* seek to newest */ + if (r < 0) + return r; + + r = sd_journal_step_one(j, advance_older); + if (r < 0) + return r; + if (r == 0) { + sd_journal_flush_matches(j); + *ret = SD_ID128_NULL; + return false; + } + if (offset == 0) { + /* If boot ID is specified without an offset, then let's short cut the loop below. */ + sd_journal_flush_matches(j); + *ret = boot_id; + return true; + } + + offset_start = advance_older ? -1 : 1; + } else { + if (advance_older) + r = sd_journal_seek_tail(j); /* seek to newest */ + else + r = sd_journal_seek_head(j); /* seek to oldest */ + if (r < 0) + return r; + + offset_start = advance_older ? 0 : 1; + } + + /* At this point the cursor is positioned at the newest/oldest entry of the reference boot ID if + * specified, or whole journal otherwise. The next invocation of _previous()/_next() will hence + * position us at the newest/oldest entry we have. */ + + for (int off = offset_start; ; off += advance_older ? -1 : 1) { BootId boot; r = discover_next_boot(j, boot_id, advance_older, &boot); @@ -1975,15 +1979,20 @@ int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret) { boot_id = boot.id; log_debug("Found boot ID %s by offset %i", SD_ID128_TO_STRING(boot_id), off); - if (off == offset) - break; + if (off == offset) { + *ret = boot_id; + return true; + } } - - *ret = boot_id; - return true; } -int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) { +int journal_get_boots( + sd_journal *j, + bool advance_older, + size_t max_ids, + BootId **ret_boots, + size_t *ret_n_boots) { + _cleanup_free_ BootId *boots = NULL; size_t n_boots = 0; int r; @@ -1992,7 +2001,12 @@ int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) { assert(ret_boots); assert(ret_n_boots); - r = sd_journal_seek_head(j); /* seek to oldest */ + sd_journal_flush_matches(j); + + if (advance_older) + r = sd_journal_seek_tail(j); /* seek to newest */ + else + r = sd_journal_seek_head(j); /* seek to oldest */ if (r < 0) return r; @@ -2005,7 +2019,10 @@ int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) { for (;;) { BootId boot; - r = discover_next_boot(j, previous_boot_id, /* advance_older = */ false, &boot); + if (n_boots >= max_ids) + break; + + r = discover_next_boot(j, previous_boot_id, advance_older, &boot); if (r < 0) return r; if (r == 0) @@ -2019,10 +2036,8 @@ int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) { * Exiting as otherwise this problem would cause an infinite loop. */ goto finish; - if (!GREEDY_REALLOC(boots, n_boots + 1)) + if (!GREEDY_REALLOC_APPEND(boots, n_boots, &boot, 1)) return -ENOMEM; - - boots[n_boots++] = boot; } finish: diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index 3a8ce8b7c1..7e7b2af901 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -49,8 +49,7 @@ int add_matches_for_unit( int add_matches_for_user_unit( sd_journal *j, - const char *unit, - uid_t uid); + const char *unit); int show_journal_by_unit( FILE *f, @@ -60,7 +59,6 @@ int show_journal_by_unit( unsigned n_columns, usec_t not_before, unsigned how_many, - uid_t uid, OutputFlags flags, int journal_open_flags, bool system_unit, @@ -72,6 +70,10 @@ void json_escape( size_t l, OutputFlags flags); -int journal_find_boot_by_id(sd_journal *j, sd_id128_t boot_id); -int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret); -int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots); +int journal_find_boot(sd_journal *j, sd_id128_t boot_id, int offset, sd_id128_t *ret); +int journal_get_boots( + sd_journal *j, + bool advance_older, + size_t max_ids, + BootId **ret_boots, + size_t *ret_n_boots); diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c index 74d6465739..2fdf321886 100644 --- a/src/systemctl/systemctl-show.c +++ b/src/systemctl/systemctl-show.c @@ -847,10 +847,9 @@ static void print_status_info( i->id, i->log_namespace, arg_output, - 0, + /* n_columns = */ 0, i->inactive_exit_timestamp_monotonic, arg_lines, - getuid(), get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, arg_runtime_scope == RUNTIME_SCOPE_SYSTEM, |