From edcf25938f1b7c3a2420b9770ff14321540d10dc Mon Sep 17 00:00:00 2001 From: Waldemar Kozaczuk Date: Sun, 19 May 2019 19:06:04 -0400 Subject: [PATCH] Enhanced __fxstata to handle AT_SYMLINK_NOFOLLOW This patch also effectively makes unmodified coreutils find work as expected: ./scripts/manifest_from_host.sh -w find && ./scripts/build fs=rofs --append-manifest ./scripts/run.py -e '/find / -ls' Signed-off-by: Waldemar Kozaczuk Message-Id: <20190519230604.11837-1-jwkozaczuk@gmail.com> --- fs/vfs/main.cc | 11 ++++++----- tests/tst-fstatat.cc | 12 +++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc index 889aa268b6..64e7f58501 100644 --- a/fs/vfs/main.cc +++ b/fs/vfs/main.cc @@ -592,10 +592,6 @@ extern "C" int __fxstatat(int ver, int dirfd, const char *pathname, struct stat *st, int flags) { - if (flags & AT_SYMLINK_NOFOLLOW) { - UNIMPLEMENTED("fstatat() with AT_SYMLINK_NOFOLLOW"); - } - if (pathname[0] == '/' || dirfd == AT_FDCWD) { return stat(pathname, st); } @@ -623,7 +619,12 @@ int __fxstatat(int ver, int dirfd, const char *pathname, struct stat *st, strlcat(p, "/", PATH_MAX); strlcat(p, pathname, PATH_MAX); - error = stat(p, st); + if (flags & AT_SYMLINK_NOFOLLOW) { + error = lstat(p, st); + } + else { + error = stat(p, st); + } vn_unlock(vp); fdrop(fp); diff --git a/tests/tst-fstatat.cc b/tests/tst-fstatat.cc index 6d3b73ebdf..a49b882a02 100644 --- a/tests/tst-fstatat.cc +++ b/tests/tst-fstatat.cc @@ -46,6 +46,7 @@ int main(int argc, char **argv) expect(fstatat(-1, "/tmp/f1", &st, 0), 0); expect(st.st_size, (off_t)0); expect_errno(fstatat(-1, "/tmp/f2", &st, 0), ENOENT); + expect_errno(fstatat(-1, "/tmp/f2", &st, AT_SYMLINK_NOFOLLOW), ENOENT); // test paths relative to cwd: char* oldwd = getcwd(NULL, 0); @@ -54,6 +55,7 @@ int main(int argc, char **argv) expect(fstatat(AT_FDCWD, "f1", &st, 0), 0); expect(st.st_size, (off_t)0); expect_errno(fstatat(AT_FDCWD, "f2", &st, 0), ENOENT); + expect_errno(fstatat(AT_FDCWD, "f2", &st, AT_SYMLINK_NOFOLLOW), ENOENT); // test paths relative to open directory: chdir("/"); @@ -63,6 +65,7 @@ int main(int argc, char **argv) expect(fstatat(dir, "f1", &st, 0), 0); expect(st.st_size, (off_t)0); expect_errno(fstatat(dir, "f2", &st, 0), ENOENT); + expect_errno(fstatat(dir, "f2", &st, AT_SYMLINK_NOFOLLOW), ENOENT); close(dir); // test operating on an open file itself (not a directory) @@ -70,10 +73,17 @@ int main(int argc, char **argv) st.st_size = 123; expect(fstatat(dir, "", &st, AT_EMPTY_PATH), 0); expect(st.st_size, (off_t)0); - close(dir); + // test AT_SYMLINK_NOFOLLOW with actual symlink + expect(symlink("/tmp/f1", "/tmp/symlink"), 0); + expect((dir = open("/tmp", 0, O_DIRECTORY)) >= 0, true); + expect(fstatat(dir, "symlink", &st, AT_SYMLINK_NOFOLLOW), 0); + expect(S_ISLNK(st.st_mode) != 0, true); + + close(dir); chdir(oldwd); free(oldwd); + remove("/tmp/symlink"); remove("/tmp/f1"); std::cout << "SUMMARY: " << tests << " tests, " << fails << " failures\n";