Merge branch 'upstream-KWSys' into update-kwsys

# By KWSys Upstream
* upstream-KWSys:
  KWSys 2019-08-29 (08f14d96)
This commit is contained in:
Brad King 2019-08-29 13:07:11 -04:00
commit 6a9de634b2
3 changed files with 82 additions and 132 deletions

View File

@ -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()

View File

@ -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());

View File

@ -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;
}