]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journald: introduce journal_file_parse_uid_from_filename() helper
authorFranck Bui <fbui@suse.com>
Mon, 14 Mar 2022 12:54:06 +0000 (13:54 +0100)
committerFranck Bui <fbui@suse.com>
Mon, 16 Jan 2023 14:04:29 +0000 (15:04 +0100)
src/journal/journald-server.c
src/libsystemd/meson.build
src/libsystemd/sd-journal/journal-file.c
src/libsystemd/sd-journal/journal-file.h
src/libsystemd/sd-journal/test-journal-file.c [new file with mode: 0644]

index 92205cca0e959458cf67349feed3cc03fd6268bd..e3ce6aaea8bc75a4676bdb1fea39edcb6e88a0e7 100644 (file)
@@ -559,9 +559,8 @@ static int server_archive_offline_user_journals(Server *s) {
         }
 
         for (;;) {
-                _cleanup_free_ char *u = NULL, *full = NULL;
+                _cleanup_free_ char *full = NULL;
                 _cleanup_close_ int fd = -EBADF;
-                const char *a, *b;
                 struct dirent *de;
                 ManagedJournalFile *f;
                 uid_t uid;
@@ -573,24 +572,14 @@ static int server_archive_offline_user_journals(Server *s) {
                                 log_ratelimit_warning_errno(errno, JOURNAL_LOG_RATELIMIT,
                                                             "Failed to enumerate %s, ignoring: %m",
                                                             s->system_storage.path);
-
                         break;
                 }
 
-                a = startswith(de->d_name, "user-");
-                if (!a)
-                        continue;
-                b = endswith(de->d_name, ".journal");
-                if (!b)
-                        continue;
-
-                u = strndup(a, b-a);
-                if (!u)
-                        return log_oom();
-
-                r = parse_uid(u, &uid);
+                r = journal_file_parse_uid_from_filename(de->d_name, &uid);
                 if (r < 0) {
-                        log_debug_errno(r, "Failed to parse UID from file name '%s', ignoring: %m", de->d_name);
+                        /* Don't warn if the file is not an online or offline user journal. */
+                        if (r != -EREMOTE)
+                                log_warning_errno(r, "Failed to parse UID from file name '%s', ignoring: %m", de->d_name);
                         continue;
                 }
 
index 9238e32980613e41e44e3e0fc4816bad26aa1cd7..7fdffec2ea07640a11c83c2d8d7af0720ac1e5e5 100644 (file)
@@ -191,6 +191,8 @@ libsystemd_pc = custom_target(
 ############################################################
 
 tests += [
+        [files('sd-journal/test-journal-file.c')],
+
         [files('sd-journal/test-journal-send.c')],
 
         [files('sd-journal/test-journal-match.c')],
index 805773474c30b90060135bd3984cd14d7f756d21..32dd4cfeb807436da24ff6f83bafc59d2645646f 100644 (file)
@@ -35,6 +35,7 @@
 #include "string-util.h"
 #include "strv.h"
 #include "sync-util.h"
+#include "user-util.h"
 #include "xattr-util.h"
 
 #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
@@ -3932,6 +3933,41 @@ fail:
         return r;
 }
 
+int journal_file_parse_uid_from_filename(const char *path, uid_t *ret_uid) {
+        _cleanup_free_ char *buf = NULL, *p = NULL;
+        const char *a, *b, *at;
+        int r;
+
+        /* This helper returns -EREMOTE when the filename doesn't match user online/offline journal
+         * pattern. Hence it currently doesn't parse archived or disposed user journals. */
+
+        assert(path);
+        assert(ret_uid);
+
+        r = path_extract_filename(path, &p);
+        if (r < 0)
+                return r;
+        if (r == O_DIRECTORY)
+                return -EISDIR;
+
+        a = startswith(p, "user-");
+        if (!a)
+                return -EREMOTE;
+        b = endswith(p, ".journal");
+        if (!b)
+                return -EREMOTE;
+
+        at = strchr(a, '@');
+        if (at)
+                return -EREMOTE;
+
+        buf = strndup(a, b-a);
+        if (!buf)
+                return -ENOMEM;
+
+        return parse_uid(buf, ret_uid);
+}
+
 int journal_file_archive(JournalFile *f, char **ret_previous_path) {
         _cleanup_free_ char *p = NULL;
 
index 1f3c80c9125d70b65b6e662248c553b777252f73..a1154a010727883a9280ae090df4f7574eca8b5d 100644 (file)
@@ -288,6 +288,7 @@ void journal_file_dump(JournalFile *f);
 void journal_file_print_header(JournalFile *f);
 
 int journal_file_archive(JournalFile *f, char **ret_previous_path);
+int journal_file_parse_uid_from_filename(const char *path, uid_t *uid);
 JournalFile* journal_initiate_close(JournalFile *f, Set *deferred_closes);
 
 int journal_file_dispose(int dir_fd, const char *fname);
diff --git a/src/libsystemd/sd-journal/test-journal-file.c b/src/libsystemd/sd-journal/test-journal-file.c
new file mode 100644 (file)
index 0000000..729de1f
--- /dev/null
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "journal-file.h"
+#include "tests.h"
+#include "user-util.h"
+
+static void test_journal_file_parse_uid_from_filename_simple(
+                const char *path,
+                uid_t expected_uid,
+                int expected_error) {
+
+        uid_t uid = UID_INVALID;
+        int r;
+
+        log_info("testing %s", path);
+
+        r = journal_file_parse_uid_from_filename(path, &uid);
+        assert_se(r == expected_error);
+        if (r < 0)
+                assert_se(uid == UID_INVALID);
+        else
+                assert_se(uid == expected_uid);
+}
+
+TEST(journal_file_parse_uid_from_filename) {
+
+        test_journal_file_parse_uid_from_filename_simple("/var/log/journal/", 0, -EISDIR);
+
+        /* The helper should return -EREMOTE for any filenames that don't look like an online or offline user
+         * journals. This includes archived and disposed journal files. */
+        test_journal_file_parse_uid_from_filename_simple("/etc/password", 0, -EREMOTE);
+        test_journal_file_parse_uid_from_filename_simple("system.journal", 0, -EREMOTE);
+        test_journal_file_parse_uid_from_filename_simple("user-1000@0005d26980bdce6e-2f2a4939583822ef.journal~", 0, -EREMOTE);
+        test_journal_file_parse_uid_from_filename_simple("user-1000@xxx-yyy-zzz.journal", 0, -EREMOTE);
+
+        test_journal_file_parse_uid_from_filename_simple("user-1000.journal", 1000, 0);
+        test_journal_file_parse_uid_from_filename_simple("user-foo.journal", 0, -EINVAL);
+        test_journal_file_parse_uid_from_filename_simple("user-65535.journal", 0, -ENXIO);
+}
+
+DEFINE_TEST_MAIN(LOG_INFO);