diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml
index 8f62c966ea..8b7035fcc2 100644
--- a/man/sd_journal_open.xml
+++ b/man/sd_journal_open.xml
@@ -32,6 +32,7 @@
SD_JOURNAL_OS_ROOT
SD_JOURNAL_ALL_NAMESPACES
SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
+ SD_JOURNAL_TAKE_DIRECTORY_FD
Open the system journal for reading
@@ -136,7 +137,13 @@
sd_journal_open_directory_fd() is similar to
sd_journal_open_directory(), but takes a file descriptor referencing a directory in the file
- system instead of an absolute file system path.
+ system instead of an absolute file system path. In addtion to the flags accepted by
+ sd_journal_open_directory(), this function also accepts
+ SD_JOURNAL_TAKE_DIRECTORY_FD. If SD_JOURNAL_TAKE_DIRECTORY_FD is
+ specified, the function will take the ownership of the specified file descriptor on success, and it will be
+ closed by sd_journal_close(), hence the caller of the function must not close the file
+ descriptor. When the flag is not specified, sd_journal_close() will not close the file
+ descriptor, so the caller should close it after sd_journal_close().
sd_journal_open_files() is similar to sd_journal_open() but takes a
NULL-terminated list of file paths to open. All files will be opened and interleaved
diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c
index 0124900517..d84b117783 100644
--- a/src/libsystemd/sd-journal/sd-journal.c
+++ b/src/libsystemd/sd-journal/sd-journal.c
@@ -2177,13 +2177,16 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
return 0;
}
-#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
+#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
(SD_JOURNAL_OS_ROOT | \
- SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+ SD_JOURNAL_SYSTEM | \
+ SD_JOURNAL_CURRENT_USER | \
+ SD_JOURNAL_TAKE_DIRECTORY_FD)
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
struct stat st;
+ bool take_fd;
int r;
assert_return(ret, -EINVAL);
@@ -2196,7 +2199,8 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
if (!S_ISDIR(st.st_mode))
return -EBADFD;
- j = journal_new(flags, NULL, NULL);
+ take_fd = FLAGS_SET(flags, SD_JOURNAL_TAKE_DIRECTORY_FD);
+ j = journal_new(flags & ~SD_JOURNAL_TAKE_DIRECTORY_FD, NULL, NULL);
if (!j)
return -ENOMEM;
@@ -2209,6 +2213,8 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
if (r < 0)
return r;
+ SET_FLAG(j->flags, SD_JOURNAL_TAKE_DIRECTORY_FD, take_fd);
+
*ret = TAKE_PTR(j);
return 0;
}
@@ -2288,6 +2294,9 @@ _public_ void sd_journal_close(sd_journal *j) {
hashmap_free(j->directories_by_path);
hashmap_free(j->directories_by_wd);
+ if (FLAGS_SET(j->flags, SD_JOURNAL_TAKE_DIRECTORY_FD))
+ safe_close(j->toplevel_fd);
+
safe_close(j->inotify_fd);
if (j->mmap) {
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index 4af540400d..7d2d75dd89 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -71,6 +71,7 @@ enum {
SD_JOURNAL_OS_ROOT = 1 << 4,
SD_JOURNAL_ALL_NAMESPACES = 1 << 5, /* Show all namespaces, not just the default or specified one */
SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE = 1 << 6, /* Show default namespace in addition to specified one */
+ SD_JOURNAL_TAKE_DIRECTORY_FD = 1 << 7, /* sd_journal_open_directory_fd() will take ownership of the provided file descriptor. */
SD_JOURNAL_SYSTEM_ONLY _sd_deprecated_ = SD_JOURNAL_SYSTEM /* old name */
};