summaryrefslogtreecommitdiff
path: root/Source/kwsys
diff options
context:
space:
mode:
Diffstat (limited to 'Source/kwsys')
-rw-r--r--Source/kwsys/CMakeLists.txt16
-rw-r--r--Source/kwsys/Directory.cxx39
-rw-r--r--Source/kwsys/Directory.hxx.in6
-rw-r--r--Source/kwsys/EncodingC.c2
-rw-r--r--Source/kwsys/Glob.hxx.in7
-rw-r--r--Source/kwsys/ProcessUNIX.c12
-rw-r--r--Source/kwsys/Status.cxx60
-rw-r--r--Source/kwsys/Status.hxx.in101
-rw-r--r--Source/kwsys/SystemInformation.cxx23
-rw-r--r--Source/kwsys/SystemTools.cxx418
-rw-r--r--Source/kwsys/SystemTools.hxx.in68
-rw-r--r--Source/kwsys/Terminal.c10
-rw-r--r--Source/kwsys/testDirectory.cxx4
-rw-r--r--Source/kwsys/testDynamicLoader.cxx23
-rw-r--r--Source/kwsys/testStatus.cxx117
-rw-r--r--Source/kwsys/testSystemTools.cxx47
16 files changed, 732 insertions, 221 deletions
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index b0a854292..ef615b3fe 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -98,6 +98,16 @@ foreach(p
endif()
endforeach()
+# Some configure checks depend upon the deployment target. Clear checks when
+# the deployment target changes.
+if (APPLE)
+ if (NOT CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL KWSYS_LAST_OSX_DEPLOYMENT_TARGET)
+ unset(KWSYS_CXX_HAS_UTIMENSAT CACHE)
+ endif ()
+ set(KWSYS_LAST_OSX_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}"
+ CACHE INTERNAL "remember the last deployment target to trigger configure rechecks")
+endif ()
+
#-----------------------------------------------------------------------------
# If a namespace is not specified, use "kwsys" and enable testing.
# This should be the case only when kwsys is not included inside
@@ -142,6 +152,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
set(KWSYS_USE_MD5 1)
set(KWSYS_USE_Process 1)
set(KWSYS_USE_RegularExpression 1)
+ set(KWSYS_USE_Status 1)
set(KWSYS_USE_System 1)
set(KWSYS_USE_SystemTools 1)
set(KWSYS_USE_CommandLineArguments 1)
@@ -157,6 +168,7 @@ if(KWSYS_USE_SystemTools)
set(KWSYS_USE_Directory 1)
set(KWSYS_USE_FStream 1)
set(KWSYS_USE_Encoding 1)
+ set(KWSYS_USE_Status 1)
endif()
if(KWSYS_USE_Glob)
set(KWSYS_USE_Directory 1)
@@ -177,6 +189,7 @@ if(KWSYS_USE_System)
endif()
if(KWSYS_USE_Directory)
set(KWSYS_USE_Encoding 1)
+ set(KWSYS_USE_Status 1)
endif()
if(KWSYS_USE_DynamicLoader)
set(KWSYS_USE_Encoding 1)
@@ -630,7 +643,7 @@ set(KWSYS_HXX_FILES Configure String)
# Add selected C++ classes.
set(cppclasses
Directory DynamicLoader Encoding Glob RegularExpression SystemTools
- CommandLineArguments FStream SystemInformation ConsoleBuf
+ CommandLineArguments FStream SystemInformation ConsoleBuf Status
)
foreach(cpp ${cppclasses})
if(KWSYS_USE_${cpp})
@@ -963,6 +976,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# C++ tests
set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
testConfigure.cxx
+ testStatus.cxx
testSystemTools.cxx
testCommandLineArguments.cxx
testCommandLineArguments1.cxx
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 0c2190aee..2e8aa83f4 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -94,7 +94,7 @@ void Directory::Clear()
namespace KWSYS_NAMESPACE {
-bool Directory::Load(const std::string& name, std::string* errorMessage)
+Status Directory::Load(std::string const& name, std::string* errorMessage)
{
this->Clear();
intptr_t srchHandle;
@@ -121,7 +121,11 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
delete[] buf;
if (srchHandle == -1) {
- return 0;
+ Status status = Status::POSIX_errno();
+ if (errorMessage) {
+ *errorMessage = status.GetString();
+ }
+ return status;
}
// Loop through names
@@ -129,7 +133,14 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
} while (_wfindnext(srchHandle, &data) != -1);
this->Internal->Path = name;
- return _findclose(srchHandle) != -1;
+ if (_findclose(srchHandle) == -1) {
+ Status status = Status::POSIX_errno();
+ if (errorMessage) {
+ *errorMessage = status.GetString();
+ }
+ return status;
+ }
+ return Status::Success();
}
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
@@ -152,6 +163,20 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
delete[] buf;
if (srchHandle == -1) {
+ if (errorMessage) {
+ if (unsigned int errorId = GetLastError()) {
+ LPSTR message = nullptr;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, nullptr);
+ *errorMessage = std::string(message, size);
+ LocalFree(message);
+ } else {
+ *errorMessage = "Unknown error.";
+ }
+ }
return 0;
}
@@ -192,7 +217,7 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
namespace KWSYS_NAMESPACE {
-bool Directory::Load(const std::string& name, std::string* errorMessage)
+Status Directory::Load(std::string const& name, std::string* errorMessage)
{
this->Clear();
@@ -203,7 +228,7 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
if (errorMessage != nullptr) {
*errorMessage = std::string(strerror(errno));
}
- return false;
+ return Status::POSIX_errno();
}
errno = 0;
@@ -214,12 +239,12 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
if (errorMessage != nullptr) {
*errorMessage = std::string(strerror(errno));
}
- return false;
+ return Status::POSIX_errno();
}
this->Internal->Path = name;
closedir(dir);
- return true;
+ return Status::Success();
}
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in
index 7bc9db024..d50111615 100644
--- a/Source/kwsys/Directory.hxx.in
+++ b/Source/kwsys/Directory.hxx.in
@@ -4,6 +4,7 @@
#define @KWSYS_NAMESPACE@_Directory_hxx
#include <@KWSYS_NAMESPACE@/Configure.h>
+#include <@KWSYS_NAMESPACE@/Status.hxx>
#include <string>
@@ -32,10 +33,9 @@ public:
/**
* Load the specified directory and load the names of the files
- * in that directory. 0 is returned if the directory can not be
- * opened, 1 if it is opened.
+ * in that directory.
*/
- bool Load(const std::string&, std::string* errorMessage = nullptr);
+ Status Load(std::string const&, std::string* errorMessage = nullptr);
/**
* Return the number of files in the current directory.
diff --git a/Source/kwsys/EncodingC.c b/Source/kwsys/EncodingC.c
index e12236afe..13127f1ac 100644
--- a/Source/kwsys/EncodingC.c
+++ b/Source/kwsys/EncodingC.c
@@ -60,7 +60,7 @@ size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* str, size_t n)
char* kwsysEncoding_DupToNarrow(const wchar_t* str)
{
char* ret = NULL;
- size_t length = kwsysEncoding_wcstombs(0, str, 0) + 1;
+ size_t length = kwsysEncoding_wcstombs(NULL, str, 0) + 1;
if (length > 0) {
ret = (char*)malloc(length);
if (ret) {
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index e8474e200..fd3977541 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -54,6 +54,9 @@ public:
Glob();
~Glob();
+ Glob(const Glob&) = delete;
+ void operator=(const Glob&) = delete;
+
//! Find all files that match the pattern.
bool FindFiles(const std::string& inexpr, GlobMessages* messages = nullptr);
@@ -124,10 +127,6 @@ protected:
std::vector<std::string> VisitedSymlinks;
bool ListDirs;
bool RecurseListDirs;
-
-private:
- Glob(const Glob&) = delete;
- void operator=(const Glob&) = delete;
};
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index e1e7721b4..a8a15ddb0 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -122,6 +122,10 @@ static inline void kwsysProcess_usleep(unsigned int msec)
/* The maximum amount to read from a pipe at a time. */
#define KWSYSPE_PIPE_BUFFER_SIZE 1024
+#if defined(__NVCOMPILER)
+# pragma diag_suppress 550 /* variable set but never used (in FD_ZERO) */
+#endif
+
/* Keep track of times using a signed representation. Switch to the
native (possibly unsigned) representation only when calling native
functions. */
@@ -2890,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:
@@ -2908,7 +2912,7 @@ static void kwsysProcessesSignalHandler(int signum
oldSigAction = &kwsysProcessesOldSigTermAction;
break;
default:
- return 0;
+ return;
}
while ((sigaction(signum, &newSigAction, oldSigAction) < 0) &&
(errno == EINTR))
diff --git a/Source/kwsys/Status.cxx b/Source/kwsys/Status.cxx
new file mode 100644
index 000000000..503d1e1d5
--- /dev/null
+++ b/Source/kwsys/Status.cxx
@@ -0,0 +1,60 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Status.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+# include "Status.hxx.in"
+#endif
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
+namespace KWSYS_NAMESPACE {
+
+Status Status::POSIX_errno()
+{
+ return Status::POSIX(errno);
+}
+
+#ifdef _WIN32
+Status Status::Windows_GetLastError()
+{
+ return Status::Windows(GetLastError());
+}
+#endif
+
+std::string Status::GetString() const
+{
+ std::string err;
+ switch (this->Kind_) {
+ case Kind::Success:
+ err = "Success";
+ break;
+ case Kind::POSIX:
+ err = strerror(this->POSIX_);
+ break;
+#ifdef _WIN32
+ case Kind::Windows: {
+ LPSTR message = NULL;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, this->Windows_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, NULL);
+ err = std::string(message, size);
+ LocalFree(message);
+ } break;
+#endif
+ };
+ return err;
+}
+
+} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/Status.hxx.in b/Source/kwsys/Status.hxx.in
new file mode 100644
index 000000000..ed46d5c2b
--- /dev/null
+++ b/Source/kwsys/Status.hxx.in
@@ -0,0 +1,101 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#ifndef @KWSYS_NAMESPACE@_Status_hxx
+#define @KWSYS_NAMESPACE@_Status_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#include <string>
+
+namespace @KWSYS_NAMESPACE@ {
+
+/** \class Status
+ * \brief OS-specific status of a system operation.
+ */
+class @KWSYS_NAMESPACE@_EXPORT Status
+{
+public:
+ enum class Kind
+ {
+ Success,
+ POSIX,
+#ifdef _WIN32
+ Windows,
+#endif
+ };
+
+ /** Construct with kind "Success". */
+ Status() = default;
+
+ /** Construct with kind "Success". */
+ static Status Success() { return Status(); }
+
+ /** Construct with kind "POSIX" using given errno-style value. */
+ static Status POSIX(int e)
+ {
+ Status s(Kind::POSIX);
+ s.POSIX_ = e;
+ return s;
+ }
+
+ /** Construct with kind "POSIX" using errno. */
+ static Status POSIX_errno();
+
+#ifdef _WIN32
+ /** Construct with kind "Windows" using given GetLastError()-style value. */
+ static Status Windows(unsigned int e)
+ {
+ Status s(Kind::Windows);
+ s.Windows_ = e;
+ return s;
+ }
+
+ /** Construct with kind "Windows" using GetLastError(). */
+ static Status Windows_GetLastError();
+#endif
+
+ /** Return true on "Success", false otherwise. */
+ explicit operator bool() const { return this->Kind_ == Kind::Success; }
+
+ /** Return the kind of status. */
+ Kind GetKind() const { return this->Kind_; }
+
+ /** If the kind is "POSIX", returns the errno-style value.
+ Otherwise, returns 0. */
+ int GetPOSIX() const
+ {
+ return this->Kind_ == Kind::POSIX ? this->POSIX_ : 0;
+ }
+
+#ifdef _WIN32
+ /** If the kind is "Windows", returns the GetLastError()-style value.
+ Otherwise, returns 0. */
+ unsigned int GetWindows() const
+ {
+ return this->Kind_ == Kind::Windows ? this->Windows_ : 0;
+ }
+#endif
+
+ /** Return a human-readable description of the status. */
+ std::string GetString() const;
+
+private:
+ Status(Kind kind)
+ : Kind_(kind)
+ {
+ }
+
+ Kind Kind_ = Kind::Success;
+
+ union
+ {
+ int POSIX_;
+#ifdef _WIN32
+ unsigned int Windows_;
+#endif
+ };
+};
+
+} // namespace @KWSYS_NAMESPACE@
+
+#endif
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 7743eabe9..12f9139cc 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1383,7 +1383,7 @@ void SymbolProperties::Initialize(void* address)
}
# else
// second fallback use builtin backtrace_symbols
-// to decode the bactrace.
+// to decode the backtrace.
# endif
}
#endif // don't define this class if we're not using it
@@ -3472,6 +3472,10 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
// We want to record the total number of cores in this->NumberOfPhysicalCPU
// (checking only the first proc)
std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores");
+ if (Cores.empty()) {
+ // Linux Sparc is different
+ Cores = this->ExtractValueFromCpuInfoFile(buffer, "ncpus probed");
+ }
auto NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str());
NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u);
this->NumberOfPhysicalCPU =
@@ -3490,6 +3494,9 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
if (this->NumberOfPhysicalCPU <= 0) {
this->NumberOfPhysicalCPU = 1;
}
+ if (this->NumberOfLogicalCPU == 0) {
+ this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+ }
// LogicalProcessorsPerPhysical>1 => SMT.
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU;
@@ -3503,8 +3510,18 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
else {
// Linux Sparc: CPU speed is in Hz and encoded in hexadecimal
CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "Cpu0ClkTck");
- this->CPUSpeedInMHz =
- static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 16)) / 1000000.0f;
+ if (!CPUSpeed.empty()) {
+ this->CPUSpeedInMHz =
+ static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 16)) /
+ 1000000.0f;
+ } else {
+ // if the kernel is build as Sparc32 it's in decimal, note the different
+ // case
+ CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "CPU0ClkTck");
+ this->CPUSpeedInMHz =
+ static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 10)) /
+ 1000000.0f;
+ }
}
#endif
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 6144d9c04..006495d3c 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -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
@@ -244,7 +278,7 @@ inline int Chdir(const std::string& dir)
return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
}
inline void Realpath(const std::string& path, std::string& resolved_path,
- std::string* errorMessage = 0)
+ std::string* errorMessage = nullptr)
{
std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
wchar_t* ptemp;
@@ -882,21 +916,24 @@ FILE* SystemTools::Fopen(const std::string& file, const char* mode)
#endif
}
-bool SystemTools::MakeDirectory(const char* path, const mode_t* mode)
+Status SystemTools::MakeDirectory(const char* path, const mode_t* mode)
{
if (!path) {
- return false;
+ return Status::POSIX(EINVAL);
}
return SystemTools::MakeDirectory(std::string(path), mode);
}
-bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
+Status SystemTools::MakeDirectory(std::string const& path, const mode_t* mode)
{
- if (SystemTools::PathExists(path)) {
- return SystemTools::FileIsDirectory(path);
- }
if (path.empty()) {
- return false;
+ return Status::POSIX(EINVAL);
+ }
+ if (SystemTools::PathExists(path)) {
+ if (SystemTools::FileIsDirectory(path)) {
+ return Status::Success();
+ }
+ return Status::POSIX(EEXIST);
}
std::string dir = path;
SystemTools::ConvertToUnixSlashes(dir);
@@ -914,15 +951,11 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
++pos;
}
topdir = dir;
- if (Mkdir(topdir, mode) != 0) {
- // if it is some other error besides directory exists
- // then return false
- if (errno != EEXIST) {
- return false;
- }
+ if (Mkdir(topdir, mode) != 0 && errno != EEXIST) {
+ return Status::POSIX_errno();
}
- return true;
+ return Status::Success();
}
// replace replace with with as many times as it shows up in source.
@@ -1411,18 +1444,18 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
#endif
}
-bool SystemTools::Touch(const std::string& filename, bool create)
+Status SystemTools::Touch(std::string const& filename, bool create)
{
if (!SystemTools::FileExists(filename)) {
if (create) {
FILE* file = Fopen(filename, "a+b");
if (file) {
fclose(file);
- return true;
+ return Status::Success();
}
- return false;
+ return Status::POSIX_errno();
} else {
- return true;
+ return Status::Success();
}
}
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -1430,31 +1463,32 @@ bool SystemTools::Touch(const std::string& filename, bool create)
FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (!h) {
- return false;
+ return Status::Windows_GetLastError();
}
FILETIME mtime;
GetSystemTimeAsFileTime(&mtime);
if (!SetFileTime(h, 0, 0, &mtime)) {
+ Status status = Status::Windows_GetLastError();
CloseHandle(h);
- return false;
+ return status;
}
CloseHandle(h);
#elif KWSYS_CXX_HAS_UTIMENSAT
// utimensat is only available on newer Unixes and macOS 10.13+
if (utimensat(AT_FDCWD, filename.c_str(), nullptr, 0) < 0) {
- return false;
+ return Status::POSIX_errno();
}
#else
// fall back to utimes
if (utimes(filename.c_str(), nullptr) < 0) {
- return false;
+ return Status::POSIX_errno();
}
#endif
- return true;
+ return Status::Success();
}
-bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
- int* result)
+Status SystemTools::FileTimeCompare(std::string const& f1,
+ std::string const& f2, int* result)
{
// Default to same time.
*result = 0;
@@ -1462,11 +1496,11 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
// POSIX version. Use stat function to get file modification time.
struct stat s1;
if (stat(f1.c_str(), &s1) != 0) {
- return false;
+ return Status::POSIX_errno();
}
struct stat s2;
if (stat(f2.c_str(), &s2) != 0) {
- return false;
+ return Status::POSIX_errno();
}
# if KWSYS_CXX_STAT_HAS_ST_MTIM
// Compare using nanosecond resolution.
@@ -1504,17 +1538,17 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
WIN32_FILE_ATTRIBUTE_DATA f2d;
if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(),
GetFileExInfoStandard, &f1d)) {
- return false;
+ return Status::Windows_GetLastError();
}
if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(),
GetFileExInfoStandard, &f2d)) {
- return false;
+ return Status::Windows_GetLastError();
}
// Compare the file times using resolution provided by system call.
*result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime);
#endif
- return true;
+ return Status::Success();
}
// Return a capitalized string (i.e the first letter is uppercased, all other
@@ -2129,8 +2163,8 @@ static std::string FileInDir(const std::string& source, const std::string& dir)
return new_destination + '/' + SystemTools::GetFilenameName(source);
}
-bool SystemTools::CopyFileIfDifferent(const std::string& source,
- const std::string& destination)
+Status SystemTools::CopyFileIfDifferent(std::string const& source,
+ std::string const& destination)
{
// special check for a destination that is a directory
// FilesDiffer does not handle file to directory compare
@@ -2147,7 +2181,7 @@ bool SystemTools::CopyFileIfDifferent(const std::string& source,
}
}
// at this point the files must be the same so return true
- return true;
+ return Status::Success();
}
#define KWSYS_ST_BUFFER 4096
@@ -2273,16 +2307,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1,
return false;
}
-/**
- * Blockwise copy source to destination file
- */
-static bool CopyFileContentBlockwise(const std::string& source,
- const std::string& destination)
+Status SystemTools::CopyFileContentBlockwise(std::string const& source,
+ std::string const& destination)
{
// Open files
kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
if (!fin) {
- return false;
+ return Status::POSIX_errno();
}
// try and remove the destination file so that read only destination files
@@ -2294,7 +2325,7 @@ static bool CopyFileContentBlockwise(const std::string& source,
kwsys::ofstream fout(destination.c_str(),
std::ios::out | std::ios::trunc | std::ios::binary);
if (!fout) {
- return false;
+ return Status::POSIX_errno();
}
// This copy loop is very sensitive on certain platforms with
@@ -2323,10 +2354,10 @@ static bool CopyFileContentBlockwise(const std::string& source,
fout.close();
if (!fout) {
- return false;
+ return Status::POSIX_errno();
}
- return true;
+ return Status::Success();
}
/**
@@ -2341,13 +2372,13 @@ static bool CopyFileContentBlockwise(const std::string& source,
* - The underlying filesystem does not support file cloning
* - An unspecified error occurred
*/
-static bool CloneFileContent(const std::string& source,
- const std::string& destination)
+Status SystemTools::CloneFileContent(std::string const& source,
+ std::string const& destination)
{
#if defined(__linux) && defined(FICLONE)
int in = open(source.c_str(), O_RDONLY);
if (in < 0) {
- return false;
+ return Status::POSIX_errno();
}
SystemTools::RemoveFile(destination);
@@ -2355,38 +2386,42 @@ static bool CloneFileContent(const std::string& source,
int out =
open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (out < 0) {
+ Status status = Status::POSIX_errno();
close(in);
- return false;
+ return status;
}
- int result = ioctl(out, FICLONE, in);
+ Status status = Status::Success();
+ if (ioctl(out, FICLONE, in) < 0) {
+ status = Status::POSIX_errno();
+ }
close(in);
close(out);
- if (result < 0) {
- return false;
- }
-
- return true;
+ return status;
#else
(void)source;
(void)destination;
- return false;
+ return Status::POSIX(ENOSYS);
#endif
}
/**
* Copy a file named by "source" to the file named by "destination".
*/
-bool SystemTools::CopyFileAlways(const std::string& source,
- const std::string& destination)
+Status SystemTools::CopyFileAlways(std::string const& source,
+ std::string const& destination)
{
+ Status status;
mode_t perm = 0;
- bool perms = SystemTools::GetPermissions(source, perm);
+ Status perms = SystemTools::GetPermissions(source, perm);
std::string real_destination = destination;
if (SystemTools::FileIsDirectory(source)) {
- SystemTools::MakeDirectory(destination);
+ status = SystemTools::MakeDirectory(destination);
+ if (!status) {
+ return status;
+ }
} else {
// If destination is a directory, try to create a file with the same
// name as the source in that directory.
@@ -2403,30 +2438,34 @@ bool SystemTools::CopyFileAlways(const std::string& source,
}
// If files are the same do not copy
if (SystemTools::SameFile(source, real_destination)) {
- return true;
+ return status;
}
// Create destination directory
-
- SystemTools::MakeDirectory(destination_dir);
-
- if (!CloneFileContent(source, real_destination)) {
- // if cloning did not succeed, fall back to blockwise copy
- if (!CopyFileContentBlockwise(source, real_destination)) {
- return false;
+ if (!destination_dir.empty()) {
+ status = SystemTools::MakeDirectory(destination_dir);
+ if (!status) {
+ return status;
}
}
+
+ status = SystemTools::CloneFileContent(source, real_destination);
+ // if cloning did not succeed, fall back to blockwise copy
+ if (!status) {
+ status = SystemTools::CopyFileContentBlockwise(source, real_destination);
+ }
+ if (!status) {
+ return status;
+ }
}
if (perms) {
- if (!SystemTools::SetPermissions(real_destination, perm)) {
- return false;
- }
+ status = SystemTools::SetPermissions(real_destination, perm);
}
- return true;
+ return status;
}
-bool SystemTools::CopyAFile(const std::string& source,
- const std::string& destination, bool always)
+Status SystemTools::CopyAFile(std::string const& source,
+ std::string const& destination, bool always)
{
if (always) {
return SystemTools::CopyFileAlways(source, destination);
@@ -2439,18 +2478,21 @@ bool SystemTools::CopyAFile(const std::string& source,
* Copy a directory content from "source" directory to the directory named by
* "destination".
*/
-bool SystemTools::CopyADirectory(const std::string& source,
- const std::string& destination, bool always)
+Status SystemTools::CopyADirectory(std::string const& source,
+ std::string const& destination, bool always)
{
+ Status status;
Directory dir;
- if (dir.Load(source) == 0) {
- return false;
+ status = dir.Load(source);
+ if (!status) {
+ return status;
}
- size_t fileNum;
- if (!SystemTools::MakeDirectory(destination)) {
- return false;
+ status = SystemTools::MakeDirectory(destination);
+ if (!status) {
+ return status;
}
- for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
+
+ for (size_t fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 &&
strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) {
std::string fullPath = source;
@@ -2460,18 +2502,20 @@ bool SystemTools::CopyADirectory(const std::string& source,
std::string fullDestPath = destination;
fullDestPath += "/";
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
- if (!SystemTools::CopyADirectory(fullPath, fullDestPath, always)) {
- return false;
+ status = SystemTools::CopyADirectory(fullPath, fullDestPath, always);
+ if (!status) {
+ return status;
}
} else {
- if (!SystemTools::CopyAFile(fullPath, destination, always)) {
- return false;
+ status = SystemTools::CopyAFile(fullPath, destination, always);
+ if (!status) {
+ return status;
}
}
}
}
- return true;
+ return status;
}
// return size of file; also returns zero if no file exists
@@ -2553,26 +2597,26 @@ std::string SystemTools::GetLastSystemError()
return strerror(e);
}
-bool SystemTools::RemoveFile(const std::string& source)
+Status SystemTools::RemoveFile(std::string const& source)
{
#ifdef _WIN32
std::wstring const& ws = Encoding::ToWindowsExtendedPath(source);
if (DeleteFileW(ws.c_str())) {
- return true;
+ return Status::Success();
}
DWORD err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
- return true;
+ return Status::Success();
}
if (err != ERROR_ACCESS_DENIED) {
- return false;
+ return Status::Windows(err);
}
/* The file may be read-only. Try adding write permission. */
mode_t mode;
if (!SystemTools::GetPermissions(source, mode) ||
!SystemTools::SetPermissions(source, S_IWRITE)) {
SetLastError(err);
- return false;
+ return Status::Windows(err);
}
const DWORD DIRECTORY_SOFT_LINK_ATTRS =
@@ -2581,26 +2625,29 @@ bool SystemTools::RemoveFile(const std::string& source)
if (attrs != INVALID_FILE_ATTRIBUTES &&
(attrs & DIRECTORY_SOFT_LINK_ATTRS) == DIRECTORY_SOFT_LINK_ATTRS &&
RemoveDirectoryW(ws.c_str())) {
- return true;
+ return Status::Success();
}
if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND ||
GetLastError() == ERROR_PATH_NOT_FOUND) {
- return true;
+ return Status::Success();
}
/* Try to restore the original permissions. */
SystemTools::SetPermissions(source, mode);
SetLastError(err);
- return false;
+ return Status::Windows(err);
#else
- return unlink(source.c_str()) == 0 || errno == ENOENT;
+ if (unlink(source.c_str()) != 0 && errno != ENOENT) {
+ return Status::POSIX_errno();
+ }
+ return Status::Success();
#endif
}
-bool SystemTools::RemoveADirectory(const std::string& source)
+Status SystemTools::RemoveADirectory(std::string const& source)
{
// Add write permission to the directory so we can modify its
// content to remove files and directories from it.
- mode_t mode;
+ mode_t mode = 0;
if (SystemTools::GetPermissions(source, mode)) {
#if defined(_WIN32) && !defined(__CYGWIN__)
mode |= S_IWRITE;
@@ -2610,8 +2657,13 @@ bool SystemTools::RemoveADirectory(const std::string& source)
SystemTools::SetPermissions(source, mode);
}
+ Status status;
Directory dir;
- dir.Load(source);
+ status = dir.Load(source);
+ if (!status) {
+ return status;
+ }
+
size_t fileNum;
for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 &&
@@ -2621,18 +2673,23 @@ bool SystemTools::RemoveADirectory(const std::string& source)
fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
if (SystemTools::FileIsDirectory(fullPath) &&
!SystemTools::FileIsSymlink(fullPath)) {
- if (!SystemTools::RemoveADirectory(fullPath)) {
- return false;
+ status = SystemTools::RemoveADirectory(fullPath);
+ if (!status) {
+ return status;
}
} else {
- if (!SystemTools::RemoveFile(fullPath)) {
- return false;
+ status = SystemTools::RemoveFile(fullPath);
+ if (!status) {
+ return status;
}
}
}
}
- return (Rmdir(source) == 0);
+ if (Rmdir(source) != 0) {
+ status = Status::POSIX_errno();
+ }
+ return status;
}
/**
@@ -2985,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);
}
@@ -3025,45 +3082,109 @@ bool SystemTools::FileIsFIFO(const std::string& name)
#endif
}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::CreateSymlink(const std::string&, const std::string&)
+Status SystemTools::CreateSymlink(std::string const& origName,
+ std::string const& newName)
{
- return false;
-}
+#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
-bool SystemTools::CreateSymlink(const std::string& origName,
- const std::string& newName)
-{
- return symlink(origName.c_str(), newName.c_str()) >= 0;
-}
+ if (symlink(origName.c_str(), newName.c_str()) < 0) {
+ return Status::POSIX_errno();
+ }
+ return Status::Success();
#endif
+}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::ReadSymlink(const std::string&, std::string&)
+Status SystemTools::ReadSymlink(std::string const& newName,
+ std::string& origName)
{
- return false;
-}
+#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
-bool SystemTools::ReadSymlink(const std::string& newName,
- std::string& origName)
-{
char buf[KWSYS_SYSTEMTOOLS_MAXPATH + 1];
int count = static_cast<int>(
readlink(newName.c_str(), buf, KWSYS_SYSTEMTOOLS_MAXPATH));
- if (count >= 0) {
- // Add null-terminator.
- buf[count] = 0;
- origName = buf;
- return true;
- } else {
- return false;
+ if (count < 0) {
+ return Status::POSIX_errno();
}
-}
+ // Add null-terminator.
+ buf[count] = 0;
+ origName = buf;
#endif
+ return Status::Success();
+}
-int SystemTools::ChangeDirectory(const std::string& dir)
+Status SystemTools::ChangeDirectory(std::string const& dir)
{
- return Chdir(dir);
+ if (Chdir(dir) < 0) {
+ return Status::POSIX_errno();
+ }
+ return Status::Success();
}
std::string SystemTools::GetCurrentWorkingDirectory()
@@ -3929,7 +4050,7 @@ bool SystemTools::FileIsFullPath(const char* in_name)
bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len)
{
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
// On Windows, the name must be at least two characters long.
if (len < 2) {
return false;
@@ -3960,7 +4081,8 @@ bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len)
return false;
}
-bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
+Status SystemTools::GetShortPath(std::string const& path,
+ std::string& shortPath)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
std::string tempPath = path; // create a buffer
@@ -3980,14 +4102,14 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
}
if (ret == 0) {
- return false;
+ return Status::Windows_GetLastError();
} else {
shortPath = Encoding::ToNarrow(&buffer[0]);
- return true;
+ return Status::Success();
}
#else
shortPath = path;
- return true;
+ return Status::Success();
#endif
}
@@ -4088,21 +4210,21 @@ int SystemTools::GetTerminalWidth()
return width;
}
-bool SystemTools::GetPermissions(const char* file, mode_t& mode)
+Status SystemTools::GetPermissions(const char* file, mode_t& mode)
{
if (!file) {
- return false;
+ return Status::POSIX(EINVAL);
}
return SystemTools::GetPermissions(std::string(file), mode);
}
-bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
+Status SystemTools::GetPermissions(std::string const& file, mode_t& mode)
{
#if defined(_WIN32)
DWORD attr =
GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str());
if (attr == INVALID_FILE_ATTRIBUTES) {
- return false;
+ return Status::Windows_GetLastError();
}
if ((attr & FILE_ATTRIBUTE_READONLY) != 0) {
mode = (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6));
@@ -4125,27 +4247,27 @@ bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
#else
struct stat st;
if (stat(file.c_str(), &st) < 0) {
- return false;
+ return Status::POSIX_errno();
}
mode = st.st_mode;
#endif
- return true;
+ return Status::Success();
}
-bool SystemTools::SetPermissions(const char* file, mode_t mode,
- bool honor_umask)
+Status SystemTools::SetPermissions(const char* file, mode_t mode,
+ bool honor_umask)
{
if (!file) {
- return false;
+ return Status::POSIX(EINVAL);
}
return SystemTools::SetPermissions(std::string(file), mode, honor_umask);
}
-bool SystemTools::SetPermissions(const std::string& file, mode_t mode,
- bool honor_umask)
+Status SystemTools::SetPermissions(std::string const& file, mode_t mode,
+ bool honor_umask)
{
if (!SystemTools::PathExists(file)) {
- return false;
+ return Status::POSIX(ENOENT);
}
if (honor_umask) {
mode_t currentMask = umask(0);
@@ -4158,10 +4280,10 @@ bool SystemTools::SetPermissions(const std::string& file, mode_t mode,
if (chmod(file.c_str(), mode) < 0)
#endif
{
- return false;
+ return Status::POSIX_errno();
}
- return true;
+ return Status::Success();
}
std::string SystemTools::GetParentDirectory(const std::string& fileOrDir)
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 74dc17651..e5d115e08 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -4,6 +4,7 @@
#define @KWSYS_NAMESPACE@_SystemTools_hxx
#include <@KWSYS_NAMESPACE@/Configure.hxx>
+#include <@KWSYS_NAMESPACE@/Status.hxx>
#include <iosfwd>
#include <map>
@@ -339,7 +340,7 @@ public:
/**
Change the modification time or create a file
*/
- static bool Touch(const std::string& filename, bool create);
+ static Status Touch(std::string const& filename, bool create);
/**
* Compare file modification times.
@@ -347,8 +348,8 @@ public:
* When true is returned, result has -1, 0, +1 for
* f1 older, same, or newer than f2.
*/
- static bool FileTimeCompare(const std::string& f1, const std::string& f2,
- int* result);
+ static Status FileTimeCompare(std::string const& f1, std::string const& f2,
+ int* result);
/**
* Get the file extension (including ".") needed for an executable
@@ -507,7 +508,7 @@ public:
* For windows return the short path for the given path,
* Unix just a pass through
*/
- static bool GetShortPath(const std::string& path, std::string& result);
+ static Status GetShortPath(std::string const& path, std::string& result);
/**
* Read line from file. Make sure to read a full line and truncates it if
@@ -553,16 +554,16 @@ public:
* can make a full path even if none of the directories existed
* prior to calling this function.
*/
- static bool MakeDirectory(const char* path, const mode_t* mode = nullptr);
- static bool MakeDirectory(const std::string& path,
- const mode_t* mode = nullptr);
+ static Status MakeDirectory(const char* path, const mode_t* mode = nullptr);
+ static Status MakeDirectory(std::string const& path,
+ const mode_t* mode = nullptr);
/**
* Copy the source file to the destination file only
* if the two files differ.
*/
- static bool CopyFileIfDifferent(const std::string& source,
- const std::string& destination);
+ static Status CopyFileIfDifferent(std::string const& source,
+ std::string const& destination);
/**
* Compare the contents of two files. Return true if different
@@ -578,6 +579,17 @@ public:
const std::string& path2);
/**
+ * Blockwise copy source to destination file
+ */
+ static Status CopyFileContentBlockwise(std::string const& source,
+ std::string const& destination);
+ /**
+ * Clone the source file to the destination file
+ */
+ static Status CloneFileContent(std::string const& source,
+ std::string const& destination);
+
+ /**
* Return true if the two files are the same file
*/
static bool SameFile(const std::string& file1, const std::string& file2);
@@ -585,16 +597,16 @@ public:
/**
* Copy a file.
*/
- static bool CopyFileAlways(const std::string& source,
- const std::string& destination);
+ static Status CopyFileAlways(std::string const& source,
+ std::string const& destination);
/**
* Copy a file. If the "always" argument is true the file is always
* copied. If it is false, the file is copied only if it is new or
* has changed.
*/
- static bool CopyAFile(const std::string& source,
- const std::string& destination, bool always = true);
+ static Status CopyAFile(std::string const& source,
+ std::string const& destination, bool always = true);
/**
* Copy content directory to another directory with all files and
@@ -602,19 +614,19 @@ public:
* always copied. If it is false, only files that have changed or
* are new are copied.
*/
- static bool CopyADirectory(const std::string& source,
- const std::string& destination,
- bool always = true);
+ static Status CopyADirectory(std::string const& source,
+ std::string const& destination,
+ bool always = true);
/**
* Remove a file
*/
- static bool RemoveFile(const std::string& source);
+ static Status RemoveFile(std::string const& source);
/**
* Remove a directory
*/
- static bool RemoveADirectory(const std::string& source);
+ static Status RemoveADirectory(std::string const& source);
/**
* Get the maximum full file path length
@@ -708,14 +720,14 @@ public:
* Create a symbolic link if the platform supports it. Returns whether
* creation succeeded.
*/
- static bool CreateSymlink(const std::string& origName,
- const std::string& newName);
+ static Status CreateSymlink(std::string const& origName,
+ std::string const& newName);
/**
* Read the contents of a symbolic link. Returns whether reading
* succeeded.
*/
- static bool ReadSymlink(const std::string& newName, std::string& origName);
+ static Status ReadSymlink(std::string const& newName, std::string& origName);
/**
* Try to locate the file 'filename' in the directory 'dir'.
@@ -765,12 +777,12 @@ public:
* WARNING: A non-thread-safe method is currently used to get the umask
* if a honor_umask parameter is set to true.
*/
- static bool GetPermissions(const char* file, mode_t& mode);
- static bool GetPermissions(const std::string& file, mode_t& mode);
- static bool SetPermissions(const char* file, mode_t mode,
- bool honor_umask = false);
- static bool SetPermissions(const std::string& file, mode_t mode,
- bool honor_umask = false);
+ static Status GetPermissions(const char* file, mode_t& mode);
+ static Status GetPermissions(std::string const& file, mode_t& mode);
+ static Status SetPermissions(const char* file, mode_t mode,
+ bool honor_umask = false);
+ static Status SetPermissions(std::string const& file, mode_t mode,
+ bool honor_umask = false);
/** -----------------------------------------------------------------
* Time Manipulation Routines
@@ -867,7 +879,7 @@ public:
/**
* Change directory to the directory specified
*/
- static int ChangeDirectory(const std::string& dir);
+ static Status ChangeDirectory(std::string const& dir);
/**
* Get the result of strerror(errno)
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index 4d1b46c87..20bb5fe6d 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -10,7 +10,7 @@
#endif
/* Configure support for this platform. */
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32)
# define KWSYS_TERMINAL_SUPPORT_CONSOLE
#endif
#if !defined(_WIN32)
@@ -173,6 +173,14 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
}
}
+ /* Disable color according to http://bixense.com/clicolors/ convention. */
+ {
+ const char* clicolor = getenv("CLICOLOR");
+ if (clicolor && strcmp(clicolor, "0") == 0) {
+ return 0;
+ }
+ }
+
/* GNU make 4.1+ may tell us that its output is destined for a TTY. */
{
const char* termout = getenv("MAKE_TERMOUT");
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
index eb3ca3254..06a22dc47 100644
--- a/Source/kwsys/testDirectory.cxx
+++ b/Source/kwsys/testDirectory.cxx
@@ -88,7 +88,7 @@ int _nonExistentDirectoryTest()
errorMessage = "foo";
// Increment res failure if directory lists
- res += testdir.Load(testdirpath, &errorMessage);
+ res += testdir.Load(testdirpath, &errorMessage) ? 1 : 0;
#if !defined(_WIN32) || defined(__CYGWIN__)
// Increment res failure if errorMessage is unmodified
res += (errorMessage == "foo");
@@ -120,7 +120,7 @@ int _copyDirectoryTest()
std::cerr << destination << " shouldn't exist before test" << std::endl;
return 2;
}
- const bool copysuccess = SystemTools::CopyADirectory(source, destination);
+ const Status copysuccess = SystemTools::CopyADirectory(source, destination);
const bool destinationexists = SystemTools::PathExists(destination);
if (copysuccess) {
std::cerr << "CopyADirectory should have returned false" << std::endl;
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index 703ad4dcd..9ba204e78 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -8,6 +8,25 @@
# include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
+// Needed for __GLIBC__ test macro.
+#ifdef __linux__
+# include <features.h>
+#endif
+
+// Will define LIBDL_SO macro on systems with glibc.
+#ifdef __GLIBC__
+# include <gnu/lib-names.h>
+// Define to LIBC_SO, if not defined by above header.
+# ifndef LIBDL_SO
+# define LIBDL_SO LIBC_SO
+# endif
+#endif
+
+// Define the LIBDL_SO macro, if not defined above.
+#ifndef LIBDL_SO
+# define LIBDL_SO "libdl.so"
+#endif
+
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
@@ -107,8 +126,8 @@ int testDynamicLoader(int argc, char* argv[])
// This one is actually fun to test, since dlopen is by default
// loaded...wonder why :)
res += TestDynamicLoader("foobar.lib", "dlopen", 0, 1, 0);
- res += TestDynamicLoader("libdl.so", "dlopen", 1, 1, 1);
- res += TestDynamicLoader("libdl.so", "TestDynamicLoader", 1, 0, 1);
+ res += TestDynamicLoader(LIBDL_SO, "dlopen", 1, 1, 1);
+ res += TestDynamicLoader(LIBDL_SO, "TestDynamicLoader", 1, 0, 1);
#endif
// Now try on the generated library
std::string libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynload");
diff --git a/Source/kwsys/testStatus.cxx b/Source/kwsys/testStatus.cxx
new file mode 100644
index 000000000..f85ef422d
--- /dev/null
+++ b/Source/kwsys/testStatus.cxx
@@ -0,0 +1,117 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Status.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+# include "Status.hxx.in"
+#endif
+
+#include <cerrno>
+#include <iostream>
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+int testStatus(int, char* [])
+{
+ bool res = true;
+ {
+ kwsys::Status status;
+ if (status.GetKind() != kwsys::Status::Kind::Success) {
+ std::cerr << "Status default constructor does not produce Success\n";
+ res = false;
+ }
+
+ status = kwsys::Status::Success();
+ if (status.GetKind() != kwsys::Status::Kind::Success) {
+ std::cerr << "Status Success constructor does not produce Success\n";
+ res = false;
+ }
+ if (!status) {
+ std::cerr << "Status Success kind is not true\n";
+ res = false;
+ }
+ if (status.GetPOSIX() != 0) {
+ std::cerr << "Status Success kind does not return POSIX 0\n";
+ res = false;
+ }
+#ifdef _WIN32
+ if (status.GetWindows() != 0) {
+ std::cerr << "Status Success kind does not return Windows 0\n";
+ res = false;
+ }
+#endif
+ if (status.GetString() != "Success") {
+ std::cerr << "Status Success kind does not return \"Success\" string\n";
+ res = false;
+ }
+
+ status = kwsys::Status::POSIX(EINVAL);
+ if (status.GetKind() != kwsys::Status::Kind::POSIX) {
+ std::cerr << "Status POSIX constructor does not produce POSIX\n";
+ res = false;
+ }
+ if (status) {
+ std::cerr << "Status POSIX kind is not false\n";
+ res = false;
+ }
+ if (status.GetPOSIX() != EINVAL) {
+ std::cerr << "Status POSIX kind does not preserve POSIX value\n";
+ res = false;
+ }
+#ifdef _WIN32
+ if (status.GetWindows() != 0) {
+ std::cerr << "Status POSIX kind does not return Windows 0\n";
+ res = false;
+ }
+#endif
+ if (status.GetString().empty()) {
+ std::cerr << "Status POSIX kind returns empty string\n";
+ res = false;
+ }
+ errno = ENOENT;
+ status = kwsys::Status::POSIX_errno();
+ if (status.GetPOSIX() != ENOENT) {
+ std::cerr << "Status POSIX_errno did not use errno\n";
+ res = false;
+ }
+ errno = 0;
+
+#ifdef _WIN32
+ status = kwsys::Status::Windows(ERROR_INVALID_PARAMETER);
+ if (status.GetKind() != kwsys::Status::Kind::Windows) {
+ std::cerr << "Status Windows constructor does not produce Windows\n";
+ res = false;
+ }
+ if (status) {
+ std::cerr << "Status Windows kind is not false\n";
+ res = false;
+ }
+ if (status.GetWindows() != ERROR_INVALID_PARAMETER) {
+ std::cerr << "Status Windows kind does not preserve Windows value\n";
+ res = false;
+ }
+ if (status.GetPOSIX() != 0) {
+ std::cerr << "Status Windows kind does not return POSIX 0\n";
+ res = false;
+ }
+ if (status.GetString().empty()) {
+ std::cerr << "Status Windows kind returns empty string\n";
+ res = false;
+ }
+
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ status = kwsys::Status::Windows_GetLastError();
+ if (status.GetWindows() != ERROR_FILE_NOT_FOUND) {
+ std::cerr << "Status Windows_GetLastError did not use GetLastError()\n";
+ res = false;
+ }
+ SetLastError(ERROR_SUCCESS);
+#endif
+ }
+ return res ? 0 : 1;
+}
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index cfa420df4..39a19cbf2 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -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.
@@ -290,15 +291,17 @@ static bool CheckFileOperations()
res = false;
}
+ std::cerr << std::oct;
// Reset umask
-#if defined(_WIN32) && !defined(__CYGWIN__)
+#ifdef __MSYS__
+ mode_t fullMask = S_IWRITE;
+#elif defined(_WIN32) && !defined(__CYGWIN__)
// NOTE: Windows doesn't support toggling _S_IREAD.
mode_t fullMask = _S_IWRITE;
#else
// On a normal POSIX platform, we can toggle all permissions.
mode_t fullMask = S_IRWXU | S_IRWXG | S_IRWXO;
#endif
- mode_t orig_umask = umask(fullMask);
// Test file permissions without umask
mode_t origPerm, thisPerm;
@@ -329,9 +332,10 @@ static bool CheckFileOperations()
// While we're at it, check proper TestFileAccess functionality.
bool do_write_test = true;
-#if defined(__linux__)
- // If we are running as root on linux ignore this check, as
- // root can always write to files
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
+ defined(__NetBSD__) || defined(__DragonFly__)
+ // If we are running as root on POSIX-ish systems (Linux and the BSDs,
+ // at least), ignore this check, as root can always write to files.
do_write_test = (getuid() != 0);
#endif
if (do_write_test &&
@@ -370,6 +374,7 @@ static bool CheckFileOperations()
res = false;
}
+ mode_t orig_umask = umask(fullMask);
// Test setting file permissions while honoring umask
if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask, true)) {
std::cerr << "Problem with SetPermissions (3) for: " << testNewFile
@@ -422,21 +427,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;
- }
+ 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(testBadSymlink, false)) {
+ std::cerr << "Problem with Touch (no create) for: " << testBadSymlink
+ << std::endl;
+ res = false;
+ }
}
-#endif
if (!kwsys::SystemTools::Touch(testNewDir, false)) {
std::cerr << "Problem with Touch (no create) for: " << testNewDir
@@ -496,6 +508,7 @@ static bool CheckFileOperations()
}
#endif
+ std::cerr << std::dec;
return res;
}
@@ -1093,7 +1106,7 @@ static bool CheckCopyFileIfDifferent()
ret = false;
continue;
}
- std::string bdata = readFile("file_b");
+ std::string bdata = readFile(cptarget);
if (diff_test_cases[i].a != bdata) {
std::cerr << "Incorrect CopyFileIfDifferent file contents in test case "
<< i + 1 << "." << std::endl;