94 lines
3.3 KiB
Diff
94 lines
3.3 KiB
Diff
|
|
From 7a2349072e165c27ed0655934b05530c19d23779 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||
|
|
Date: Thu, 15 Feb 2024 07:01:17 +0900
|
||
|
|
Subject: [PATCH] fs-util: readlinkat() supports an empty string
|
||
|
|
|
||
|
|
From readlinkat(2):
|
||
|
|
Since Linux 2.6.39, pathname can be an empty string, in which case the
|
||
|
|
call operates on the symbolic link referred to by dirfd (which should
|
||
|
|
have been obtained using open(2) with the O_PATH and O_NOFOLLOW flags).
|
||
|
|
|
||
|
|
(cherry picked from commit e4c094c05543410ba05a16f757d1e11652f4f6bd)
|
||
|
|
(cherry picked from commit 30142e781d7afcfa93185d2543f59e9cf90dc882)
|
||
|
|
|
||
|
|
Conflict:NA
|
||
|
|
Reference:https://github.com/systemd/systemd-stable/commit/7a2349072e165c27ed0655934b05530c19d23779
|
||
|
|
---
|
||
|
|
src/basic/fs-util.c | 8 ++++++--
|
||
|
|
src/test/test-fs-util.c | 35 +++++++++++++++++++++++++++++++++++
|
||
|
|
2 files changed, 41 insertions(+), 2 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
|
||
|
|
index ee38e0266a..9ba9268d77 100644
|
||
|
|
--- a/src/basic/fs-util.c
|
||
|
|
+++ b/src/basic/fs-util.c
|
||
|
|
@@ -116,7 +116,11 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
|
||
|
|
int readlinkat_malloc(int fd, const char *p, char **ret) {
|
||
|
|
size_t l = PATH_MAX;
|
||
|
|
|
||
|
|
- assert(p);
|
||
|
|
+ assert(fd >= 0 || fd == AT_FDCWD);
|
||
|
|
+
|
||
|
|
+ if (fd < 0 && isempty(p))
|
||
|
|
+ return -EISDIR; /* In this case, the fd points to the current working directory, and is
|
||
|
|
+ * definitely not a symlink. Let's return earlier. */
|
||
|
|
|
||
|
|
for (;;) {
|
||
|
|
_cleanup_free_ char *c = NULL;
|
||
|
|
@@ -126,7 +130,7 @@ int readlinkat_malloc(int fd, const char *p, char **ret) {
|
||
|
|
if (!c)
|
||
|
|
return -ENOMEM;
|
||
|
|
|
||
|
|
- n = readlinkat(fd, p, c, l);
|
||
|
|
+ n = readlinkat(fd, strempty(p), c, l);
|
||
|
|
if (n < 0)
|
||
|
|
return -errno;
|
||
|
|
|
||
|
|
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
|
||
|
|
index 5de1eea0d4..ef335b43ae 100644
|
||
|
|
--- a/src/test/test-fs-util.c
|
||
|
|
+++ b/src/test/test-fs-util.c
|
||
|
|
@@ -758,4 +758,39 @@ static int intro(void) {
|
||
|
|
return EXIT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
+TEST(readlinkat_malloc) {
|
||
|
|
+ _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
|
||
|
|
+ _cleanup_close_ int tfd = -EBADF, fd = -EBADF;
|
||
|
|
+ _cleanup_free_ char *p = NULL, *q = NULL;
|
||
|
|
+ const char *expect = "hgoehogefoobar";
|
||
|
|
+
|
||
|
|
+ tfd = mkdtemp_open(NULL, O_PATH, &t);
|
||
|
|
+ assert_se(tfd >= 0);
|
||
|
|
+
|
||
|
|
+ assert_se(symlinkat(expect, tfd, "linkname") >= 0);
|
||
|
|
+
|
||
|
|
+ assert_se(readlinkat_malloc(tfd, "linkname", &p) >= 0);
|
||
|
|
+ assert_se(streq(p, expect));
|
||
|
|
+ p = mfree(p);
|
||
|
|
+
|
||
|
|
+ fd = openat(tfd, "linkname", O_PATH | O_NOFOLLOW | O_CLOEXEC);
|
||
|
|
+ assert_se(fd >= 0);
|
||
|
|
+ assert_se(readlinkat_malloc(fd, NULL, &p) >= 0);
|
||
|
|
+ assert_se(streq(p, expect));
|
||
|
|
+ p = mfree(p);
|
||
|
|
+ assert_se(readlinkat_malloc(fd, "", &p) >= 0);
|
||
|
|
+ assert_se(streq(p, expect));
|
||
|
|
+ p = mfree(p);
|
||
|
|
+ fd = safe_close(fd);
|
||
|
|
+
|
||
|
|
+ assert_se(q = path_join(t, "linkname"));
|
||
|
|
+ assert_se(readlinkat_malloc(AT_FDCWD, q, &p) >= 0);
|
||
|
|
+ assert_se(streq(p, expect));
|
||
|
|
+ p = mfree(p);
|
||
|
|
+ assert_se(readlinkat_malloc(INT_MAX, q, &p) >= 0);
|
||
|
|
+ assert_se(streq(p, expect));
|
||
|
|
+ p = mfree(p);
|
||
|
|
+ q = mfree(q);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|