From 6a2cb8131e5213224b2ecfc0dc6649a945319e4c Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 7 Mar 2017 16:10:10 +0000 Subject: [PATCH] [Support] Add the option to not follow symlinks on stat. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297154 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/FileSystem.h | 11 +++++++---- lib/Support/Path.cpp | 4 ++-- lib/Support/Unix/Path.inc | 4 ++-- lib/Support/Windows/Path.inc | 25 ++++++++----------------- 4 files changed, 19 insertions(+), 25 deletions(-) diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 0fbec088a83..64893dc3575 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -481,9 +481,9 @@ inline bool is_local(int FD) { /// @brief Does status represent a directory? /// -/// @param status A file_status previously returned from status. -/// @returns status.type() == file_type::directory_file. -file_type get_file_type(const Twine &Path); +/// @param Path The path to get the type of. +/// @returns A value from the file_type enumeration indicating the type of file. +file_type get_file_type(const Twine &Path, bool follow = true); /// @brief Does status represent a directory? /// @@ -552,9 +552,12 @@ std::error_code is_other(const Twine &path, bool &result); /// /// @param path Input path. /// @param result Set to the file status. +/// @param follow When true, follows symlinks. Otherwise, the symlink itself is +/// statted. /// @returns errc::success if result has been successfully set, otherwise a /// platform-specific error_code. -std::error_code status(const Twine &path, file_status &result); +std::error_code status(const Twine &path, file_status &result, + bool follow = true); /// @brief A version for when a file descriptor is already available. std::error_code status(int FD, file_status &Result); diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp index 94ed1876bbd..3eee85fc3f7 100644 --- a/lib/Support/Path.cpp +++ b/lib/Support/Path.cpp @@ -953,9 +953,9 @@ bool status_known(file_status s) { return s.type() != file_type::status_error; } -file_type get_file_type(const Twine &Path) { +file_type get_file_type(const Twine &Path, bool Follow) { file_status st; - if (status(Path, st)) + if (status(Path, st, Follow)) return file_type::status_error; return st.type(); } diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index 629a04b6c5b..05636f8bcf3 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -510,12 +510,12 @@ static std::error_code fillStatus(int StatRet, const struct stat &Status, return std::error_code(); } -std::error_code status(const Twine &Path, file_status &Result) { +std::error_code status(const Twine &Path, file_status &Result, bool Follow) { SmallString<128> PathStorage; StringRef P = Path.toNullTerminatedStringRef(PathStorage); struct stat Status; - int StatRet = ::stat(P.begin(), &Status); + int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status); return fillStatus(StatRet, Status, Result); } diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index d9e1ff4ffe4..d2a2c0fb8e9 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -551,7 +551,7 @@ handle_status_error: return mapWindowsError(LastError); } -std::error_code status(const Twine &path, file_status &result) { +std::error_code status(const Twine &path, file_status &result, bool Follow) { SmallString<128> path_storage; SmallVector path_utf16; @@ -568,28 +568,19 @@ std::error_code status(const Twine &path, file_status &result) { if (attr == INVALID_FILE_ATTRIBUTES) return getStatus(INVALID_HANDLE_VALUE, result); + DWORD Flags = FILE_FLAG_BACKUP_SEMANTICS; // Handle reparse points. - if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { - ScopedFileHandle h( - ::CreateFileW(path_utf16.begin(), - 0, // Attributes only. - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - 0)); - if (!h) - return getStatus(INVALID_HANDLE_VALUE, result); - } + if (!Follow && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) + Flags |= FILE_FLAG_OPEN_REPARSE_POINT; ScopedFileHandle h( ::CreateFileW(path_utf16.begin(), 0, // Attributes only. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - if (!h) - return getStatus(INVALID_HANDLE_VALUE, result); + NULL, OPEN_EXISTING, Flags, 0)); + if (!h) + return getStatus(INVALID_HANDLE_VALUE, result); - return getStatus(h, result); + return getStatus(h, result); } std::error_code status(int FD, file_status &Result) { -- 2.11.0