From 02d47bd2108d46cf9790500a7568a7523df485f9 Mon Sep 17 00:00:00 2001
From: xujing <xujing125@huawei.com>
Date: Fri, 26 Aug 2022 20:32:37 +0800
Subject: [PATCH] delete journal files except system.journal when journal~
 is generated

In the case of time change and system panic, the function of invoking
sd_journal_next to obtain logs may not meet expectations(rsyslog cannot obtain
logs). Therefore, when the journal~ file is generated, delete all journal files
except system.journal, to ensure that the sd_journal_next function meets user
expectations.
---
 meson.build                              |  2 ++
 src/basic/dirent-util.c                  | 24 +++++++++++++++++
 src/basic/dirent-util.h                  |  2 ++
 src/libsystemd/sd-journal/journal-file.c | 34 ++++++++++++++++++++++++
 src/libsystemd/sd-journal/sd-journal.c   | 22 ---------------
 5 files changed, 62 insertions(+), 22 deletions(-)

diff --git a/meson.build b/meson.build
index 7419e2b..4d6ce88 100644
--- a/meson.build
+++ b/meson.build
@@ -1893,6 +1893,8 @@ basic_includes = include_directories(
         'src/basic',
         'src/fundamental',
         'src/systemd',
+        'src/libsystemd/sd-id128',
+        'src/libsystemd/sd-journal',
         '.')
 
 libsystemd_includes = [basic_includes, include_directories(
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
index 17df6a2..e362554 100644
--- a/src/basic/dirent-util.c
+++ b/src/basic/dirent-util.c
@@ -7,6 +7,8 @@
 #include "path-util.h"
 #include "stat-util.h"
 #include "string-util.h"
+#include "id128-util.h"
+#include "syslog-util.h"
 
 int dirent_ensure_type(int dir_fd, struct dirent *de) {
         STRUCT_STATX_DEFINE(sx);
@@ -65,6 +67,28 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
         return endswith(de->d_name, suffix);
 }
 
+bool dirent_is_journal_subdir(const struct dirent *de) {
+        const char *e, *n;
+        assert(de);
+
+        /* returns true if the specified directory entry looks like a directory that might contain journal
+         * files we might be interested in, i.e. is either a 128bit ID or a 128bit ID suffixed by a
+         * namespace. */
+
+        if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN))
+                return false;
+
+        e = strchr(de->d_name, '.');
+        if (!e)
+                return id128_is_valid(de->d_name); /* No namespace */
+
+        n = strndupa(de->d_name, e - de->d_name);
+        if (!id128_is_valid(n))
+                return false;
+
+        return log_namespace_name_valid(e + 1);
+}
+
 struct dirent *readdir_ensure_type(DIR *d) {
         int r;
 
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
index 0a2fcbf..de6edb2 100644
--- a/src/basic/dirent-util.h
+++ b/src/basic/dirent-util.h
@@ -12,6 +12,8 @@ bool dirent_is_file(const struct dirent *de) _pure_;
 bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
 int dirent_ensure_type(int dir_fd, struct dirent *de);
 
+bool dirent_is_journal_subdir(const struct dirent *de);
+
 struct dirent *readdir_ensure_type(DIR *d);
 struct dirent *readdir_no_dot(DIR *dirp);
 
diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c
index 93a3717..40347e9 100644
--- a/src/libsystemd/sd-journal/journal-file.c
+++ b/src/libsystemd/sd-journal/journal-file.c
@@ -40,6 +40,7 @@
 #include "sync-util.h"
 #include "user-util.h"
 #include "xattr-util.h"
+#include "dirent-util.h"
 
 #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
 #define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
@@ -4385,8 +4386,35 @@ int journal_file_archive(JournalFile *f, char **ret_previous_path) {
         return 0;
 }
 
+static void delete_dumped_journal_files(const char *path) {
+        _cleanup_closedir_ DIR *d = NULL;
+
+        d = opendir(path);
+        if (!d)
+                return;
+
+        FOREACH_DIRENT_ALL(de, d, return) {
+                if (IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN) &&
+                           (endswith(de->d_name, ".journal") ||
+                            endswith(de->d_name, ".journal~")) &&
+                           strcmp(de->d_name, "system.journal") != 0)
+                        (void) unlinkat_deallocate(dirfd(d), de->d_name, 0);
+
+                if (dirent_is_journal_subdir(de)) {
+                        _cleanup_free_ char *sub_path = NULL;
+
+                        sub_path = path_join(path, de->d_name);
+                        if (!sub_path)
+                                continue;
+
+                        delete_dumped_journal_files(sub_path);
+                }
+        }
+}
+
 int journal_file_dispose(int dir_fd, const char *fname) {
         _cleanup_free_ char *p = NULL;
+        dual_timestamp boot_timestamp;
 
         assert(fname);
 
@@ -4407,6 +4435,12 @@ int journal_file_dispose(int dir_fd, const char *fname) {
         if (renameat(dir_fd, fname, dir_fd, p) < 0)
                 return -errno;
 
+        dual_timestamp_now(&boot_timestamp);
+        if (boot_timestamp.monotonic < 10*USEC_PER_MINUTE) {
+                delete_dumped_journal_files("/var/log/journal");
+                return 0;
+        }
+
         return 0;
 }
 
diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c
index 494313d..33334ef 100644
--- a/src/libsystemd/sd-journal/sd-journal.c
+++ b/src/libsystemd/sd-journal/sd-journal.c
@@ -1647,28 +1647,6 @@ static bool dirent_is_journal_file(const struct dirent *de) {
                 endswith(de->d_name, ".journal~");
 }
 
-static bool dirent_is_journal_subdir(const struct dirent *de) {
-        const char *e, *n;
-        assert(de);
-
-        /* returns true if the specified directory entry looks like a directory that might contain journal
-         * files we might be interested in, i.e. is either a 128-bit ID or a 128-bit ID suffixed by a
-         * namespace. */
-
-        if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN))
-                return false;
-
-        e = strchr(de->d_name, '.');
-        if (!e)
-                return id128_is_valid(de->d_name); /* No namespace */
-
-        n = strndupa_safe(de->d_name, e - de->d_name);
-        if (!id128_is_valid(n))
-                return false;
-
-        return log_namespace_name_valid(e + 1);
-}
-
 static int directory_open(sd_journal *j, const char *path, DIR **ret) {
         DIR *d;
 
-- 
2.33.0

