OSDN Git Service

[Support] Add the option to not follow symlinks on stat.
authorZachary Turner <zturner@google.com>
Tue, 7 Mar 2017 16:10:10 +0000 (16:10 +0000)
committerZachary Turner <zturner@google.com>
Tue, 7 Mar 2017 16:10:10 +0000 (16:10 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297154 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/FileSystem.h
lib/Support/Path.cpp
lib/Support/Unix/Path.inc
lib/Support/Windows/Path.inc

index 0fbec08..64893dc 100644 (file)
@@ -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);
index 94ed187..3eee85f 100644 (file)
@@ -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();
 }
index 629a04b..05636f8 100644 (file)
@@ -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);
 }
 
index d9e1ff4..d2a2c0f 100644 (file)
@@ -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<wchar_t, 128> 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) {