lstat should resolve the final path component if it ends in a slash.

PiperOrigin-RevId: 239896221
Change-Id: I0949981fe50c57131c5631cdeb10b225648575c0
This commit is contained in:
Nicolas Lacasse
2019-03-22 17:38:13 -07:00
committed by Shentubot
parent 3d0b960112
commit b81bfd6013
2 changed files with 30 additions and 1 deletions
+5 -1
View File
@@ -78,7 +78,11 @@ func Lstat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return 0, nil, err
}
return 0, nil, fileOpOn(t, linux.AT_FDCWD, path, false /* resolve */, func(root *fs.Dirent, d *fs.Dirent) error {
// If the path ends in a slash (i.e. dirPath is true), then we *do*
// want to resolve the final component.
resolve := dirPath
return 0, nil, fileOpOn(t, linux.AT_FDCWD, path, resolve, func(root *fs.Dirent, d *fs.Dirent) error {
return stat(t, d, dirPath, statAddr)
})
}
+25
View File
@@ -374,6 +374,31 @@ TEST_F(StatTest, ChildOfNonDir) {
EXPECT_THAT(lstat(filename.c_str(), &st), SyscallFailsWithErrno(ENOTDIR));
}
// Test lstating a symlink directory.
TEST_F(StatTest, LstatSymlinkDir) {
// Create a directory and symlink to it.
const auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
const std::string symlink_to_dir = NewTempAbsPath();
EXPECT_THAT(symlink(dir.path().c_str(), symlink_to_dir.c_str()),
SyscallSucceeds());
auto cleanup = Cleanup([&symlink_to_dir]() {
EXPECT_THAT(unlink(symlink_to_dir.c_str()), SyscallSucceeds());
});
// Lstat on the symlink should return symlink data.
struct stat st = {};
ASSERT_THAT(lstat(symlink_to_dir.c_str(), &st), SyscallSucceeds());
EXPECT_FALSE(S_ISDIR(st.st_mode));
EXPECT_TRUE(S_ISLNK(st.st_mode));
// Lstat on the symlink with a trailing slash should return the directory
// data.
ASSERT_THAT(lstat(absl::StrCat(symlink_to_dir, "/").c_str(), &st),
SyscallSucceeds());
EXPECT_TRUE(S_ISDIR(st.st_mode));
EXPECT_FALSE(S_ISLNK(st.st_mode));
}
// Verify that we get an ELOOP from too many symbolic links even when there
// are directories in the middle.
TEST_F(StatTest, LstatELOOPPath) {