]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #32747 from YHNdnzj/tmpfiles-ret-gather
authorLuca Boccassi <bluca@debian.org>
Fri, 10 May 2024 13:04:30 +0000 (15:04 +0200)
committerGitHub <noreply@github.com>
Fri, 10 May 2024 13:04:30 +0000 (15:04 +0200)
tmpfiles: some cleanups/follow-up

19 files changed:
NEWS
man/journalctl.xml
src/basic/mkdir.c
src/basic/time-util.h
src/core/service.c
src/core/unit.c
src/journal/journalctl-filter.c
src/journal/journalctl-misc.c
src/journal/journalctl-util.c
src/journal/journalctl-util.h
src/journal/journalctl.c
src/libsystemd/sd-journal/test-journal-interleaving.c
src/login/loginctl.c
src/machine/machinectl.c
src/partition/repart.c
src/shared/logs-show.c
src/shared/logs-show.h
src/systemctl/systemctl-show.c
test/test-network/systemd-networkd-tests.py

diff --git a/NEWS b/NEWS
index 6a84faff1ebb48a3033ea53e6796fa0f07a15660..90dcf765643d06c430147bb271782a961fff307a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -416,7 +416,7 @@ CHANGES WITH 256-rc1:
 
         * systemd-nspawn will tint the terminal background for containers in a
           blueish color. This can be controller with the new --background=
-          switch.
+          switch or the new $SYSTEMD_TINT_BACKGROUND environment variable.
 
         * systemd-nspawn gained support for the 'owneridmap' option for --bind=
           mounts to map the target directory owner from inside the container to
@@ -566,7 +566,7 @@ CHANGES WITH 256-rc1:
 
         * systemd-boot's automatic SecureBoot enrollment support gained support
           for enrolling "dbx" too (Previously, only db/KEK/PK enrollment was
-          supported). It also now supports UEFI "Custom" mode.
+          supported). It also now supports UEFI "Custom" and "Audit" modes.
 
         * The pcrlock policy is saved in an unencrypted credential file
           "pcrlock.<entry-token>.cred" under XBOOTLDR/ESP in the
@@ -611,7 +611,8 @@ CHANGES WITH 256-rc1:
         * systemd-run/run0 will now tint the terminal background on supported
           terminals: in a reddish tone when invoking a root service, in a
           yellowish tone otherwise. This may be controlled and turned off via
-          the new --background= switch.
+          the new --background= switch or the new $SYSTEMD_TINT_BACKGROUND
+          environment variable.
 
         * systemd-run gained a new option '--ignore-failure' to suppress
           command failures.
@@ -695,6 +696,14 @@ CHANGES WITH 256-rc1:
         * A new environment variable $SYSTEMD_VMSPAWN_QEMU_EXTRA may carry
           additional qemu command line options to pass to qemu.
 
+        * systemd-machined gained a new GetMachineSSHInfo() D-Bus method that is
+          used by systemd-vmspawn to fetch the information needed to ssh into the
+          machine.
+
+        * systemd-machined gained a new Varlink interface that is used by
+          systemd-vmspawn to register machines with additional information and
+          metadata.
+
         systemd-repart:
 
         * systemd-repart gained new options --generate-fstab= and
@@ -730,6 +739,15 @@ CHANGES WITH 256-rc1:
           libkmod might cause problems with boot. This affects dracut <= 101,
           see https://github.com/dracut-ng/dracut-ng/commit/04b362d713235459cf.
 
+        * systemd ELF binaries that use libraries via dlopen() are now built with
+          a new ELF header note section, following a new specification defined at
+          docs/ELF_DLOPEN_METADATA.md, that provides information about which
+          sonames are loaded and used if found at runtime. This allows tools and
+          packagers to programmatically discover the list of optional
+          dependencies used by all systemd ELF binaries. A parser with packaging
+          integration tools is available at
+          https://github.com/systemd/package-notes
+
         * The sd-journal API gained a new call
           sd_journal_stream_fd_with_namespace() which is just like
           sd_journal_stream_fd() but creates a log stream targeted at a
index 7d6820064ec792922fac3999ffc41510ba56e022..caa10a056b687dae057c7c5ceb115b4fea6513e2 100644 (file)
       <varlistentry>
         <term><option>--list-boots</option></term>
 
-        <listitem><para>Show a tabular list of boot numbers (relative to the current boot), their IDs, and
-        the timestamps of the first and last message pertaining to the boot.</para>
-
-        <xi:include href="version-info.xml" xpointer="v209"/></listitem>
+        <listitem>
+          <para>Show a tabular list of boot numbers (relative to the current boot), their IDs, and the
+          timestamps of the first and last message pertaining to the boot. When specified with
+          <option>-n/--lines=<optional>+</optional><replaceable>N</replaceable></option> option, only the
+          first (when the number prefixed with <literal>+</literal>) or the last (without prefix)
+          <replaceable>N</replaceable> entries will be shown. When specified with
+          <option>-r/--reverse</option>, the list will be shown in the reverse order.</para>
+
+          <xi:include href="version-info.xml" xpointer="v209"/>
+        </listitem>
       </varlistentry>
 
       <varlistentry>
index 20329e04c2dba17745352c67d35b6c0ea5f4f6e1..f87de0a2bf58b993bfb885f74b5e5a00c1778d45 100644 (file)
@@ -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)
index b28ab8242fb203f87f9ef4aa306a388521f1aa1d..f273770233ad9b6db3b2b177de703f4456ffb598 100644 (file)
@@ -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);
 
index 9c30067e922a8ad514bb83528b5168140abebd12..3fb3cae844273811ae69da3c8550f672f5fc446d 100644 (file)
@@ -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);
 }
index 4b290934fc6c204276f5d19530472566cc1cf956..0b2460cada0a5fa52987a1571bd7d634595f3ff0 100644 (file)
@@ -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)
index 1fdde5eb37932c0a787def0103497343171dc2d2..f9eb9f8c58a38e7e622bc228a0732b93a98aebd2 100644 (file)
@@ -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");
index 47eb72575ab92e86d9bbeab1a174d8a848535f82..8ca6ea214368c51c38c1f224e87e42c43f378ee1 100644 (file)
@@ -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);
         }
index 575488bee1ad74ceb8f6412e49585b519d25bcdc..32cdaf83812a01d171fa48212213db4e7e52e399 100644 (file)
@@ -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;
+}
index 38f634f8280624e5aa1f148cd99918d052221a2f..ea3e56838d3dbe33fd93bc625ef19d803c81aae9 100644 (file)
@@ -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);
index f634d33a975bae8987e596a1fd28e983484341c2..45173a68133246a60021cc8f97ccff5d400f9f65 100644 (file)
@@ -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.");
 
index ed1918d10385c4503d774af0b1c68c918e0e2c6f..d98b3ce8cbeea3722f9f271189999f41ebcb60d3 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;
 
@@ -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);
index 8236dc2dc839fa848a314f35361aa76456538b8b..cf3bff437a0bc2840d4ee354dee4f12c9dae509c 100644 (file)
@@ -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;
index 42b7fef720466e5ca0e4149f9973c6e60193e72a..1b63e6d203786225522e07535986b4a13c566193 100644 (file)
@@ -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);
         }
 }
 
index 4196576daa97534f9e52b6eb808c79d650365801..7f7b68f9ff4741fcfe1b895cc99a526f43526773 100644 (file)
@@ -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;
                         }
                 }
index d5b131a187f580cfd2256f90a6ab74ca483c246c..c71c868889cf4b861febfd761e4d00f791ad2297 100644 (file)
@@ -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:
index 3a8ce8b7c12d63ad45b18b41894f96b3ec0aaad0..7e7b2af901e960fb0982fada81f84da7d58731b4 100644 (file)
@@ -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);
index 74d6465739dda2d4da2d86c0524c5d96352a9831..2fdf32188684e62d66fb9e4c1000d5ce4db2a743 100644 (file)
@@ -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,
index c0affc57d5c11e7e6d998cc5156c6e7904af9f75..da74eabce3d433f8de78644ead476475624ac2d3 100755 (executable)
@@ -73,6 +73,7 @@ asan_options = None
 lsan_options = None
 ubsan_options = None
 with_coverage = False
+show_journal = True # When true, show journal on stopping networkd.
 
 active_units = []
 protected_links = {
@@ -268,6 +269,22 @@ def expectedFailureIfNetdevsimWithSRIOVIsNotAvailable():
 
     return f
 
+def expectedFailureIfKernelReturnsInvalidFlags():
+    '''
+    This checks the kernel bug caused by 3ddc2231c8108302a8229d3c5849ee792a63230d.
+    It will be fixed by the following patch:
+    https://patchwork.kernel.org/project/netdevbpf/patch/20240510072932.2678952-1-edumazet@google.com/
+    '''
+    def f(func):
+        call_quiet('ip link add dummy98 type dummy')
+        call_quiet('ip link set up dev dummy98')
+        call_quiet('ip address add 192.0.2.1/24 dev dummy98 noprefixroute')
+        output = check_output('ip address show dev dummy98')
+        remove_link('dummy98')
+        return func if 'noprefixroute' in output else unittest.expectedFailure(func)
+
+    return f
+
 # pylint: disable=C0415
 def compare_kernel_version(min_kernel_version):
     try:
@@ -843,6 +860,8 @@ def networkd_is_failed():
     return call_quiet('systemctl is-failed -q systemd-networkd.service') != 1
 
 def stop_networkd(show_logs=True):
+    global show_journal
+    show_logs = show_logs and show_journal
     if show_logs:
         invocation_id = networkd_invocation_id()
     check_output('systemctl stop systemd-networkd.socket')
@@ -856,6 +875,8 @@ def start_networkd():
     check_output('systemctl start systemd-networkd')
 
 def restart_networkd(show_logs=True):
+    global show_journal
+    show_logs = show_logs and show_journal
     if show_logs:
         invocation_id = networkd_invocation_id()
     check_output('systemctl restart systemd-networkd.service')
@@ -2818,6 +2839,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
 
         check_json(networkctl_json())
 
+    @expectedFailureIfKernelReturnsInvalidFlags()
     def test_address_static(self):
         copy_network_unit('25-address-static.network', '12-dummy.netdev', copy_dropins=False)
         self.setup_nftset('addr4', 'ipv4_addr')
@@ -6290,6 +6312,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.assertIn('DHCPREPLY(veth-peer)', output)
         self.assertIn('sent size:  0 option: 14 rapid-commit', output)
 
+    @expectedFailureIfKernelReturnsInvalidFlags()
     def test_dhcp_client_ipv4_only(self):
         copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network')
 
@@ -7749,6 +7772,7 @@ if __name__ == '__main__':
     parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
     parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
     parser.add_argument('--with-coverage', help='Loosen certain sandbox restrictions to make gcov happy', dest='with_coverage', type=bool, nargs='?', const=True, default=with_coverage)
+    parser.add_argument('--no-journal', help='Do not show journal of systemd-networkd on stop', dest='show_journal', action='store_false')
     ns, unknown_args = parser.parse_known_args(namespace=unittest)
 
     if ns.build_dir:
@@ -7776,6 +7800,7 @@ if __name__ == '__main__':
     lsan_options = ns.lsan_options
     ubsan_options = ns.ubsan_options
     with_coverage = ns.with_coverage
+    show_journal = ns.show_journal
 
     if use_valgrind:
         # Do not forget the trailing space.