[PATCH 7/9] test: self: dirfd: add tests for absolute symlinks

Sascha Hauer s.hauer at pengutronix.de
Tue Oct 20 00:09:32 PDT 2026


Add tests for resolving absolute symlinks, both relative to the regular
root directory and relative to an O_CHROOT dirfd, where they must be
resolved from the root of the mount. This includes links pointing to the
root directory itself, both as last and as intermediate path component.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 test/self/dirfd.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/test/self/dirfd.c b/test/self/dirfd.c
index 04cbf6e285..be927f0761 100644
--- a/test/self/dirfd.c
+++ b/test/self/dirfd.c
@@ -96,6 +96,64 @@ static void do_test_dirfd(const char *at, int dirfd,
 }
 
 
+static void check_link(const char *at, int dirfd, const char *path,
+		       const struct stat *target)
+{
+	struct stat s;
+	int ret;
+
+	ret = statat(dirfd, path, &s);
+	if (!expect(ret == 0, target != NULL, "statat(%s, %s): %m", at, path))
+		return;
+
+	if (target)
+		expect(s.st_ino == target->st_ino, true,
+		       "statat(%s, %s) resolved to the wrong file", at, path);
+}
+
+static void test_dirfd_symlinks(void)
+{
+	struct stat root, mntroot, testfile;
+	int fd, ret;
+
+	ret = mkdir("/dirfdtest/sub", 0777);
+	if (!expect(ret == 0, true, "mkdir(\"/dirfdtest/sub\") = %d", ret))
+		return;
+
+	ret = symlink("/testfile", "/dirfdtest/sub/abslink");
+	expect(ret == 0, true, "symlink(/testfile) = %d", ret);
+	ret = symlink("/dirfdtest/testfile", "/dirfdtest/sub/fulllink");
+	expect(ret == 0, true, "symlink(/dirfdtest/testfile) = %d", ret);
+	ret = symlink("/", "/dirfdtest/sub/rootlink");
+	expect(ret == 0, true, "symlink(/) = %d", ret);
+
+	if (!expect(stat("/", &root), 0, "stat(/)") ||
+	    !expect(stat("/dirfdtest", &mntroot), 0, "stat(/dirfdtest)") ||
+	    !expect(stat("/dirfdtest/testfile", &testfile), 0,
+		    "stat(/dirfdtest/testfile)"))
+		return;
+
+	/* absolute symlinks are resolved from the root directory... */
+	check_link("AT_FDCWD", AT_FDCWD, "/dirfdtest/sub/abslink", NULL);
+	check_link("AT_FDCWD", AT_FDCWD, "/dirfdtest/sub/fulllink", &testfile);
+	check_link("AT_FDCWD", AT_FDCWD, "/dirfdtest/sub/rootlink", &root);
+	check_link("AT_FDCWD", AT_FDCWD, "/dirfdtest/sub/rootlink/", &root);
+	check_link("AT_FDCWD", AT_FDCWD,
+		   "/dirfdtest/sub/rootlink/dirfdtest/testfile", &testfile);
+
+	/* ...which is the root of the mount for O_CHROOT */
+	fd = open("/dirfdtest", O_PATH | O_CHROOT);
+	if (!expect(fd >= 0, true, "open(/dirfdtest, O_PATH | O_CHROOT) = %d", fd))
+		return;
+
+	check_link("/dirfdtest O_CHROOT", fd, "sub/abslink", &testfile);
+	check_link("/dirfdtest O_CHROOT", fd, "sub/fulllink", NULL);
+	check_link("/dirfdtest O_CHROOT", fd, "sub/rootlink", &mntroot);
+	check_link("/dirfdtest O_CHROOT", fd, "sub/rootlink/testfile", &testfile);
+
+	close(fd);
+}
+
 static void test_dirfd(void)
 {
 	int fd, ret;
@@ -116,6 +174,8 @@ static void test_dirfd(void)
 	if (!expect(ret == 0, true, "write_file() = %d", ret))
 		goto out;
 
+	test_dirfd_symlinks();
+
 #define B(dot, dotdot, zero, dev) 0b##dev##zero##dotdot##dot
 	/* We do fiften tests for every configuration
 	 * for dir in ./ /dirfdtest / ../ ; do

-- 
2.47.3




More information about the barebox mailing list