1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

Merge branch 'upstream-KWSys' into update-kwsys

# By KWSys Upstream
* upstream-KWSys:
  KWSys 2021-05-07 (979d7db0)
This commit is contained in:
Brad King
2021-05-07 09:26:05 -04:00
4 changed files with 133 additions and 32 deletions

View File

@@ -2894,10 +2894,10 @@ static void kwsysProcessesSignalHandler(int signum
/* Re-Install our handler. Repeat call until it is not interrupted. */
{
struct sigaction newSigAction;
struct sigaction& oldSigAction;
struct sigaction* oldSigAction;
memset(&newSigAction, 0, sizeof(struct sigaction));
newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
newSigChldAction.sa_flags = SA_NOCLDSTOP;
newSigAction.sa_handler = kwsysProcessesSignalHandler;
newSigAction.sa_flags = SA_NOCLDSTOP;
sigemptyset(&newSigAction.sa_mask);
switch (signum) {
case SIGCHLD:
@@ -2912,7 +2912,7 @@ static void kwsysProcessesSignalHandler(int signum
oldSigAction = &kwsysProcessesOldSigTermAction;
break;
default:
return 0;
return;
}
while ((sigaction(signum, &newSigAction, oldSigAction) < 0) &&
(errno == EINTR))

View File

@@ -70,7 +70,7 @@ public:
#ifdef _WIN32
/** If the kind is "Windows", returns the GetLastError()-style value.
Otherwise, returns 0. */
int GetWindows() const
unsigned int GetWindows() const
{
return this->Kind_ == Kind::Windows ? this->Windows_ : 0;
}

View File

@@ -93,9 +93,43 @@
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
# ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
# endif
# if defined(_MSC_VER) && _MSC_VER >= 1800
# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# endif
// from ntifs.h, which can only be used by drivers
typedef struct _REPARSE_DATA_BUFFER
{
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union
{
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct
{
UCHAR DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#endif
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
@@ -3008,7 +3042,7 @@ bool SystemTools::FileIsSymlink(const std::string& name)
}
CloseHandle(hFile);
ULONG reparseTag =
reinterpret_cast<PREPARSE_GUID_DATA_BUFFER>(&buffer[0])->ReparseTag;
reinterpret_cast<PREPARSE_DATA_BUFFER>(&buffer[0])->ReparseTag;
return (reparseTag == IO_REPARSE_TAG_SYMLINK) ||
(reparseTag == IO_REPARSE_TAG_MOUNT_POINT);
}
@@ -3048,31 +3082,90 @@ bool SystemTools::FileIsFIFO(const std::string& name)
#endif
}
#if defined(_WIN32) && !defined(__CYGWIN__)
Status SystemTools::CreateSymlink(std::string const&, std::string const&)
{
return Status::Windows(ERROR_NOT_SUPPORTED);
}
#else
Status SystemTools::CreateSymlink(std::string const& origName,
std::string const& newName)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
DWORD flags;
if (FileIsDirectory(origName)) {
flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
} else {
flags = 0;
}
std::wstring origPath = Encoding::ToWindowsExtendedPath(origName);
std::wstring newPath = Encoding::ToWindowsExtendedPath(newName);
Status status;
if (!CreateSymbolicLinkW(newPath.c_str(), origPath.c_str(),
flags |
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) {
status = Status::Windows_GetLastError();
}
// Older Windows versions do not understand
// SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
if (status.GetWindows() == ERROR_INVALID_PARAMETER) {
status = Status::Success();
if (!CreateSymbolicLinkW(newPath.c_str(), origPath.c_str(), flags)) {
status = Status::Windows_GetLastError();
}
}
return status;
#else
if (symlink(origName.c_str(), newName.c_str()) < 0) {
return Status::POSIX_errno();
}
return Status::Success();
}
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
Status SystemTools::ReadSymlink(std::string const&, std::string&)
{
return Status::Windows(ERROR_NOT_SUPPORTED);
}
#else
Status SystemTools::ReadSymlink(std::string const& newName,
std::string& origName)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
std::wstring newPath = Encoding::ToWindowsExtendedPath(newName);
// FILE_ATTRIBUTE_REPARSE_POINT means:
// * a file or directory that has an associated reparse point, or
// * a file that is a symbolic link.
HANDLE hFile = CreateFileW(
newPath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (hFile == INVALID_HANDLE_VALUE) {
return Status::Windows_GetLastError();
}
byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
DWORD bytesReturned = 0;
Status status;
if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, nullptr, 0, buffer,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned,
nullptr)) {
status = Status::Windows_GetLastError();
}
CloseHandle(hFile);
if (!status) {
return status;
}
PREPARSE_DATA_BUFFER data =
reinterpret_cast<PREPARSE_DATA_BUFFER>(&buffer[0]);
USHORT substituteNameLength;
PCWSTR substituteNameData;
if (data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
substituteNameLength =
data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
substituteNameData = data->SymbolicLinkReparseBuffer.PathBuffer +
data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
} else if (data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
substituteNameLength =
data->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
substituteNameData = data->MountPointReparseBuffer.PathBuffer +
data->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
} else {
return Status::Windows(ERROR_REPARSE_TAG_MISMATCH);
}
std::wstring substituteName(substituteNameData, substituteNameLength);
origName = Encoding::ToNarrow(substituteName);
#else
char buf[KWSYS_SYSTEMTOOLS_MAXPATH + 1];
int count = static_cast<int>(
readlink(newName.c_str(), buf, KWSYS_SYSTEMTOOLS_MAXPATH));
@@ -3082,9 +3175,9 @@ Status SystemTools::ReadSymlink(std::string const& newName,
// Add null-terminator.
buf[count] = 0;
origName = buf;
#endif
return Status::Success();
}
#endif
Status SystemTools::ChangeDirectory(std::string const& dir)
{

View File

@@ -29,6 +29,7 @@
# ifdef _MSC_VER
# define umask _umask
# endif
# include <windows.h>
#endif
#include <sys/stat.h> /* umask (POSIX), _S_I* constants (Windows) */
// Visual C++ does not define mode_t.
@@ -425,21 +426,28 @@ static bool CheckFileOperations()
res = false;
}
#if !defined(_WIN32)
std::string const testBadSymlink(testNewDir + "/badSymlink.txt");
std::string const testBadSymlinkTgt(testNewDir + "/missing/symlinkTgt.txt");
if (!kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink)) {
std::cerr << "Problem with CreateSymlink for: " << testBadSymlink << " -> "
<< testBadSymlinkTgt << std::endl;
res = false;
}
if (!kwsys::SystemTools::Touch(testBadSymlink, false)) {
std::cerr << "Problem with Touch (no create) for: " << testBadSymlink
<< std::endl;
res = false;
}
kwsys::Status const symlinkStatus =
kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink);
#if defined(_WIN32)
// Under Windows, the user may not have enough privileges to create symlinks
if (symlinkStatus.GetWindows() != ERROR_PRIVILEGE_NOT_HELD)
#endif
{
if (!symlinkStatus) {
std::cerr << "CreateSymlink for: " << testBadSymlink << " -> "
<< testBadSymlinkTgt
<< " failed: " << symlinkStatus.GetString() << std::endl;
res = false;
}
if (!kwsys::SystemTools::Touch(testBadSymlink, false)) {
std::cerr << "Problem with Touch (no create) for: " << testBadSymlink
<< std::endl;
res = false;
}
}
if (!kwsys::SystemTools::Touch(testNewDir, false)) {
std::cerr << "Problem with Touch (no create) for: " << testNewDir