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

KWSys 2021-04-14 (7ab1c601)

Code extracted from:

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

at commit 7ab1c60177e76707fbdd462fdbf7304ad2532edc (master).

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

Brad King (11):
      85e76a10 Status: Add class to hold an OS-specific status of a system operation
      eec0add2 Directory: Return Status from Load
      955e7c1e SystemTools: Return Status from RemoveFile and RemoveADirectory
      c5a99e59 SystemTools: Return Status from GetPermissions and SetPermissions
      fadfd7a0 SystemTools: Return Status from Touch
      06216f0b SystemTools: Return Status from FileTimeCompare
      ab198a22 SystemTools: Return Status from GetShortPath
      2446b205 SystemTools: Return Status from MakeDirectory
      6aec6af9 SystemTools: Return Status from ChangeDirectory
      0664553b SystemTools: Return Status from copy operations
      a95f61cf SystemTools: Return Status from symlink operations
This commit is contained in:
KWSys Upstream
2021-04-14 12:02:30 -04:00
committed by Brad King
parent d0b9ffb630
commit a790167101
9 changed files with 503 additions and 191 deletions

View File

@@ -142,6 +142,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 +158,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 +179,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 +633,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 +966,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

View File

@@ -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,21 +121,11 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
delete[] buf;
if (srchHandle == -1) {
Status status = Status::POSIX_errno();
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.";
}
*errorMessage = status.GetString();
}
return false;
return status;
}
// Loop through names
@@ -143,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,
@@ -220,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();
@@ -231,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;
@@ -242,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,

View File

@@ -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.

60
Status.cxx Normal file
View File

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

101
Status.hxx.in Normal file
View File

@@ -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. */
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

View File

@@ -882,21 +882,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 +917,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 +1410,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 +1429,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 +1462,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 +1504,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 +2129,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 +2147,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,13 +2273,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1,
return false;
}
bool SystemTools::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
@@ -2291,7 +2291,7 @@ bool SystemTools::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
@@ -2320,10 +2320,10 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source,
fout.close();
if (!fout) {
return false;
return Status::POSIX_errno();
}
return true;
return Status::Success();
}
/**
@@ -2338,13 +2338,13 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source,
* - The underlying filesystem does not support file cloning
* - An unspecified error occurred
*/
bool SystemTools::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);
@@ -2352,38 +2352,42 @@ bool SystemTools::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.
@@ -2400,30 +2404,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 (!SystemTools::CloneFileContent(source, real_destination)) {
// if cloning did not succeed, fall back to blockwise copy
if (!SystemTools::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);
@@ -2436,18 +2444,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;
@@ -2457,18 +2468,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
@@ -2550,26 +2563,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 =
@@ -2578,26 +2591,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;
@@ -2607,8 +2623,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 &&
@@ -2618,18 +2639,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;
}
/**
@@ -3023,44 +3049,49 @@ bool SystemTools::FileIsFIFO(const std::string& name)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
bool SystemTools::CreateSymlink(const std::string&, const std::string&)
Status SystemTools::CreateSymlink(std::string const&, std::string const&)
{
return false;
return Status::Windows(ERROR_NOT_SUPPORTED);
}
#else
bool SystemTools::CreateSymlink(const std::string& origName,
const std::string& newName)
Status SystemTools::CreateSymlink(std::string const& origName,
std::string const& 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&, std::string&)
{
return false;
return Status::Windows(ERROR_NOT_SUPPORTED);
}
#else
bool SystemTools::ReadSymlink(const std::string& newName,
std::string& origName)
Status SystemTools::ReadSymlink(std::string const& 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;
return Status::Success();
}
#endif
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()
@@ -3957,7 +3988,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
@@ -3977,14 +4009,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
}
@@ -4085,21 +4117,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));
@@ -4122,27 +4154,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);
@@ -4155,10 +4187,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)

View File

@@ -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
@@ -580,13 +581,13 @@ public:
/**
* Blockwise copy source to destination file
*/
static bool CopyFileContentBlockwise(const std::string& source,
const std::string& destination);
static Status CopyFileContentBlockwise(std::string const& source,
std::string const& destination);
/**
* Clone the source file to the destination file
*/
static bool CloneFileContent(const std::string& source,
const std::string& destination);
static Status CloneFileContent(std::string const& source,
std::string const& destination);
/**
* Return true if the two files are the same file
@@ -596,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
@@ -613,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
@@ -719,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'.
@@ -776,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
@@ -878,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)

View File

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

117
testStatus.cxx Normal file
View File

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