Pārlūkot izejas kodu

KWSys 2019-08-29 (08f14d96)

Code extracted from:

    https://gitlab.kitware.com/utils/kwsys.git

at commit 08f14d96b449e5d1e166998b363da16167a3ac82 (master).

Upstream Shortlog
-----------------

Ben Boeckel (1):
      9afecb09 SystemTools: fix typo in junction functions

Jon Chronopoulos (1):
      38486236 SystemTools: do not special case a junction in RemoveFile

Rolf Eike Beer (3):
      b747462d CMake: drop needless x${VAR} tricks
      1ed70242 tests: verify SystemTools::CopyFileIfDifferent()
      f73d1b4f SystemTools: factor out "dest is directory" case from CopyFileIfDifferent()
KWSys Upstream 6 gadi atpakaļ
vecāks
revīzija
f9a3f13415
3 mainītis faili ar 82 papildinājumiem un 132 dzēšanām
  1. 4 4
      CMakeLists.txt
  2. 13 110
      SystemTools.cxx
  3. 65 18
      testSystemTools.cxx

+ 4 - 4
CMakeLists.txt

@@ -121,8 +121,8 @@ if(KWSYS_CXX_STANDARD)
   set(CMAKE_CXX_STANDARD "${KWSYS_CXX_STANDARD}")
 elseif(NOT DEFINED CMAKE_CXX_STANDARD AND NOT DEFINED KWSYS_CXX_STANDARD)
   if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
-     AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"
-     AND "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU"
+     AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"
+     AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU"
     )
     set(CMAKE_CXX_STANDARD 14)
   else()
@@ -1013,7 +1013,7 @@ ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}")
 
 # Disable deprecation warnings for standard C functions.
 IF(MSVC OR (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "Intel" OR
-   (CMAKE_C_COMPILER_ID STREQUAL "Clang"  AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"))))
+   (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))))
   ADD_DEFINITIONS(
     -D_CRT_NONSTDC_NO_DEPRECATE
     -D_CRT_SECURE_NO_DEPRECATE
@@ -1104,7 +1104,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
       SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
         testConsoleBuf.cxx
         )
-      IF("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND
+      IF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND
          CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506")
         set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8)
       ENDIF()

+ 13 - 110
SystemTools.cxx

@@ -2169,24 +2169,24 @@ std::string SystemTools::ConvertToWindowsOutputPath(const std::string& path)
   return ret;
 }
 
+/**
+ * Append the filename from the path source to the directory name dir.
+ */
+static std::string FileInDir(const std::string& source, const std::string& dir)
+{
+  std::string new_destination = dir;
+  SystemTools::ConvertToUnixSlashes(new_destination);
+  return new_destination + '/' + SystemTools::GetFilenameName(source);
+}
+
 bool SystemTools::CopyFileIfDifferent(const std::string& source,
                                       const std::string& destination)
 {
   // special check for a destination that is a directory
   // FilesDiffer does not handle file to directory compare
   if (SystemTools::FileIsDirectory(destination)) {
-    std::string new_destination = destination;
-    SystemTools::ConvertToUnixSlashes(new_destination);
-    new_destination += '/';
-    std::string source_name = source;
-    new_destination += SystemTools::GetFilenameName(source_name);
-    if (SystemTools::FilesDiffer(source, new_destination)) {
-      return SystemTools::CopyFileAlways(source, destination);
-    } else {
-      // the files are the same so the copy is done return
-      // true
-      return true;
-    }
+    const std::string new_destination = FileInDir(source, destination);
+    return SystemTools::CopyFileIfDifferent(source, new_destination);
   }
   // source and destination are files so do a copy if they
   // are different
@@ -2612,101 +2612,6 @@ std::string SystemTools::GetLastSystemError()
   return strerror(e);
 }
 
-#ifdef _WIN32
-
-static bool IsJunction(const std::wstring& source)
-{
-#  ifdef FSCTL_GET_REPARSE_POINT
-  const DWORD JUNCTION_ATTRS =
-    FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
-  DWORD attrs = GetFileAttributesW(source.c_str());
-  if (attrs == INVALID_FILE_ATTRIBUTES) {
-    return false;
-  }
-  if ((attrs & JUNCTION_ATTRS) != JUNCTION_ATTRS) {
-    return false;
-  }
-
-  // Adjust privileges so that we can succefully open junction points.
-  HANDLE token;
-  TOKEN_PRIVILEGES privs;
-  OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
-  LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &privs.Privileges[0].Luid);
-  privs.PrivilegeCount = 1;
-  privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-  AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL,
-                        NULL);
-  CloseHandle(token);
-
-  HANDLE dir = CreateFileW(
-    source.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
-    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
-  if (dir == INVALID_HANDLE_VALUE) {
-    return false;
-  }
-
-  // Query whether this is a reparse point or not.
-  BYTE buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
-  REPARSE_GUID_DATA_BUFFER* reparse_buffer = (REPARSE_GUID_DATA_BUFFER*)buffer;
-  DWORD sentinel;
-
-  BOOL success =
-    DeviceIoControl(dir, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_buffer,
-                    MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &sentinel, NULL);
-
-  CloseHandle(dir);
-
-  return (success &&
-          (reparse_buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT));
-#  else
-  return false;
-#  endif
-}
-
-static bool DeleteJunction(const std::wstring& source)
-{
-#  ifdef FSCTL_DELETE_REPARSE_POINT
-  // Adjust privileges so that we can succefully open junction points as
-  // read/write.
-  HANDLE token;
-  TOKEN_PRIVILEGES privs;
-  OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
-  LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &privs.Privileges[0].Luid);
-  privs.PrivilegeCount = 1;
-  privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-  AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL,
-                        NULL);
-  CloseHandle(token);
-
-  HANDLE dir = CreateFileW(
-    source.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
-    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
-  if (dir == INVALID_HANDLE_VALUE) {
-    return false;
-  }
-
-  // Set up the structure so that we can delete the junction.
-  std::vector<BYTE> buffer(REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, 0);
-  REPARSE_GUID_DATA_BUFFER* reparse_buffer =
-    (REPARSE_GUID_DATA_BUFFER*)&buffer[0];
-  DWORD sentinel;
-
-  reparse_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
-
-  BOOL success = DeviceIoControl(
-    dir, FSCTL_DELETE_REPARSE_POINT, reparse_buffer,
-    REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &sentinel, NULL);
-
-  CloseHandle(dir);
-
-  return !!success;
-#  else
-  return false;
-#  endif
-}
-
-#endif
-
 bool SystemTools::RemoveFile(const std::string& source)
 {
 #ifdef _WIN32
@@ -2728,9 +2633,7 @@ bool SystemTools::RemoveFile(const std::string& source)
     SetLastError(err);
     return false;
   }
-  if (IsJunction(ws) && DeleteJunction(ws)) {
-    return true;
-  }
+
   const DWORD DIRECTORY_SOFT_LINK_ATTRS =
     FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
   DWORD attrs = GetFileAttributesW(ws.c_str());

+ 65 - 18
testSystemTools.cxx

@@ -999,30 +999,45 @@ static bool writeFile(const char* fileName, const char* data)
   return true;
 }
 
+static std::string readFile(const char* fileName)
+{
+  kwsys::ifstream in(fileName, std::ios::binary);
+  std::stringstream sstr;
+  sstr << in.rdbuf();
+  std::string data = sstr.str();
+  if (!in) {
+    std::cerr << "Failed to read file: " << fileName << std::endl;
+    return std::string();
+  }
+  return data;
+}
+
+struct
+{
+  const char* a;
+  const char* b;
+  bool differ;
+} diff_test_cases[] = { { "one", "one", false },
+                        { "one", "two", true },
+                        { "", "", false },
+                        { "\n", "\r\n", false },
+                        { "one\n", "one\n", false },
+                        { "one\r\n", "one\n", false },
+                        { "one\n", "one", false },
+                        { "one\ntwo", "one\ntwo", false },
+                        { "one\ntwo", "one\r\ntwo", false } };
+
 static bool CheckTextFilesDiffer()
 {
-  struct
-  {
-    const char* a;
-    const char* b;
-    bool differ;
-  } test_cases[] = { { "one", "one", false },
-                     { "one", "two", true },
-                     { "", "", false },
-                     { "\n", "\r\n", false },
-                     { "one\n", "one\n", false },
-                     { "one\r\n", "one\n", false },
-                     { "one\n", "one", false },
-                     { "one\ntwo", "one\ntwo", false },
-                     { "one\ntwo", "one\r\ntwo", false } };
-  const int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
+  const int num_test_cases =
+    sizeof(diff_test_cases) / sizeof(diff_test_cases[0]);
   for (int i = 0; i < num_test_cases; ++i) {
-    if (!writeFile("file_a", test_cases[i].a) ||
-        !writeFile("file_b", test_cases[i].b)) {
+    if (!writeFile("file_a", diff_test_cases[i].a) ||
+        !writeFile("file_b", diff_test_cases[i].b)) {
       return false;
     }
     if (kwsys::SystemTools::TextFilesDiffer("file_a", "file_b") !=
-        test_cases[i].differ) {
+        diff_test_cases[i].differ) {
       std::cerr << "Incorrect TextFilesDiffer result for test case " << i + 1
                 << "." << std::endl;
       return false;
@@ -1032,6 +1047,36 @@ static bool CheckTextFilesDiffer()
   return true;
 }
 
+static bool CheckCopyFileIfDifferent()
+{
+  bool ret = true;
+  const int num_test_cases =
+    sizeof(diff_test_cases) / sizeof(diff_test_cases[0]);
+  for (int i = 0; i < num_test_cases; ++i) {
+    if (!writeFile("file_a", diff_test_cases[i].a) ||
+        !writeFile("file_b", diff_test_cases[i].b)) {
+      return false;
+    }
+    const char* cptarget =
+      i < 4 ? TEST_SYSTEMTOOLS_BINARY_DIR "/file_b" : "file_b";
+    if (!kwsys::SystemTools::CopyFileIfDifferent("file_a", cptarget)) {
+      std::cerr << "CopyFileIfDifferent() returned false for test case "
+                << i + 1 << "." << std::endl;
+      ret = false;
+      continue;
+    }
+    std::string bdata = readFile("file_b");
+    if (diff_test_cases[i].a != bdata) {
+      std::cerr << "Incorrect CopyFileIfDifferent file contents in test case "
+                << i + 1 << "." << std::endl;
+      ret = false;
+      continue;
+    }
+  }
+
+  return ret;
+}
+
 int testSystemTools(int, char* [])
 {
   bool res = true;
@@ -1077,5 +1122,7 @@ int testSystemTools(int, char* [])
 
   res &= CheckTextFilesDiffer();
 
+  res &= CheckCopyFileIfDifferent();
+
   return res ? 0 : 1;
 }