]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journalctl: fix support of --boot=ID±offset format
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 26 Apr 2024 02:27:12 +0000 (11:27 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 10 May 2024 02:43:57 +0000 (11:43 +0900)
Fixes a regression introduced by e44f06065bf20e8d0e4adacff61350ebd36f299e.

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().

src/journal/journalctl-util.c
src/libsystemd/sd-journal/test-journal-interleaving.c
src/shared/logs-show.c
src/shared/logs-show.h

index 2e7e652fba78d13aa03770b72db5d4154565e541..32cdaf83812a01d171fa48212213db4e7e52e399 100644 (file)
@@ -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);
+        } 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 offset (%+i): %m",
+                        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 offset (%+i).",
+                                               "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);
-        } 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));
+
+                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;
index ed1918d10385c4503d774af0b1c68c918e0e2c6f..6f438915355ca052f5b01bba7aaf065c8adcf533 100644 (file)
@@ -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);
index be797afdf6c52e4355a1bb41f03a4bbc245d6349..069fcde4bfe93a6b3554b2a387c6fc21f6fecb0a 100644 (file)
@@ -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) {
index da1bbe04207ee35260dcfcd0820ed69aeb43139a..b1b42bdae76913ca9612e830944cdcbd7129303e 100644 (file)
@@ -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);