Commit 7ab1c601 authored by Brad King's avatar Brad King Committed by Kitware Robot
Browse files

Merge topic 'Status'

a95f61cf SystemTools: Return Status from symlink operations
0664553b SystemTools: Return Status from copy operations
6aec6af9 SystemTools: Return Status from ChangeDirectory
2446b205 SystemTools: Return Status from MakeDirectory
ab198a22 SystemTools: Return Status from GetShortPath
06216f0b SystemTools: Return Status from FileTimeCompare
fadfd7a0 SystemTools: Return Status from Touch
c5a99e59

 SystemTools: Return Status from GetPermissions and SetPermissions
...
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Reviewed-by: Ben Boeckel's avatarBen Boeckel <ben.boeckel@kitware.com>
Merge-request: !210
parents db93a594 a95f61cf
......@@ -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
......
......@@ -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,
......
......@@ -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.
......
/* 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
/* 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
This diff is collapsed.
......@@ -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)
......
......@@ -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;
......
/* 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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment