journalctl: fix support of --boot=ID±offset format
Fixes a regression introduced by e44f06065b.
After the offending commit, if a boot ID suffixed with an offset is
specified to --boot=, the boot ID was ignored.
This fixes the issue.
To fix the issue, this merges journal_find_boot_by_id() and
journal_find_boot_by_offset().
This commit is contained in:
@@ -94,24 +94,26 @@ int journal_acquire_boot(sd_journal *j) {
|
||||
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 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);
|
||||
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 ID (%s): %m",
|
||||
SD_ID128_TO_STRING(arg_boot_id));
|
||||
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 ID (%s).",
|
||||
SD_ID128_TO_STRING(arg_boot_id));
|
||||
"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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -471,24 +471,25 @@ static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) {
|
||||
assert_se(journal_get_boots(j, &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 (int i = - (int) n_boots + 1; i <= (int) n_boots; i++) {
|
||||
for (size_t i = 0; i < n_boots; i++) {
|
||||
sd_id128_t id;
|
||||
|
||||
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);
|
||||
/* 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));
|
||||
}
|
||||
}
|
||||
|
||||
test_done(t);
|
||||
|
||||
+48
-48
@@ -1909,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);
|
||||
@@ -1950,21 +1922,50 @@ int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret) {
|
||||
|
||||
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;
|
||||
if (!sd_id128_is_null(boot_id)) {
|
||||
r = add_match_boot_id(j, boot_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* 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 (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;
|
||||
|
||||
sd_id128_t boot_id = SD_ID128_NULL;
|
||||
for (int off = !advance_older; ; off += advance_older ? -1 : 1) {
|
||||
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);
|
||||
@@ -1978,12 +1979,11 @@ 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) {
|
||||
|
||||
@@ -70,6 +70,5 @@ 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_find_boot(sd_journal *j, sd_id128_t boot_id, int offset, sd_id128_t *ret);
|
||||
int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots);
|
||||
|
||||
Reference in New Issue
Block a user