diff options
Diffstat (limited to 'test/API/driver/kwsys/SystemTools.cxx')
-rw-r--r-- | test/API/driver/kwsys/SystemTools.cxx | 4703 |
1 files changed, 0 insertions, 4703 deletions
diff --git a/test/API/driver/kwsys/SystemTools.cxx b/test/API/driver/kwsys/SystemTools.cxx deleted file mode 100644 index ce4d6ef..0000000 --- a/test/API/driver/kwsys/SystemTools.cxx +++ /dev/null @@ -1,4703 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ -#ifdef __osf__ -# define _OSF_SOURCE -# define _POSIX_C_SOURCE 199506L -# define _XOPEN_SOURCE_EXTENDED -#endif - -#if defined(_WIN32) && \ - (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || \ - defined(__MINGW32__)) -# define KWSYS_WINDOWS_DIRS -#else -# if defined(__SUNPRO_CC) -# include <fcntl.h> -# endif -#endif - -#include "kwsysPrivate.h" -#include KWSYS_HEADER(RegularExpression.hxx) -#include KWSYS_HEADER(SystemTools.hxx) -#include KWSYS_HEADER(Directory.hxx) -#include KWSYS_HEADER(FStream.hxx) -#include KWSYS_HEADER(Encoding.h) -#include KWSYS_HEADER(Encoding.hxx) - -#include <fstream> -#include <iostream> -#include <set> -#include <sstream> -#include <utility> -#include <vector> - -// Work-around CMake dependency scanning limitation. This must -// duplicate the above list of headers. -#if 0 -# include "Directory.hxx.in" -# include "Encoding.hxx.in" -# include "FStream.hxx.in" -# include "RegularExpression.hxx.in" -# include "SystemTools.hxx.in" -#endif - -#ifdef _MSC_VER -# pragma warning(disable : 4786) -#endif - -#if defined(__sgi) && !defined(__GNUC__) -# pragma set woff 1375 /* base class destructor not virtual */ -#endif - -#include <ctype.h> -#include <errno.h> -#ifdef __QNX__ -# include <malloc.h> /* for malloc/free on QNX */ -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__) -# include <strings.h> /* for strcasecmp */ -#endif - -#ifdef _MSC_VER -# define umask _umask // Note this is still umask on Borland -#endif - -// support for realpath call -#ifndef _WIN32 -# include <limits.h> -# include <pwd.h> -# include <sys/ioctl.h> -# include <sys/time.h> -# include <sys/wait.h> -# include <unistd.h> -# include <utime.h> -# ifndef __VMS -# include <sys/param.h> -# include <termios.h> -# endif -# include <signal.h> /* sigprocmask */ -#endif - -#ifdef __linux -# include <linux/fs.h> -#endif - -// Windows API. -#if defined(_WIN32) -# include <windows.h> -# include <winioctl.h> -# ifndef INVALID_FILE_ATTRIBUTES -# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) -# endif -# if defined(_MSC_VER) && _MSC_VER >= 1800 -# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx -# endif -#elif defined(__CYGWIN__) -# include <windows.h> -# undef _WIN32 -#endif - -#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H -extern char** environ; -#endif - -#ifdef __CYGWIN__ -# include <sys/cygwin.h> -#endif - -// getpwnam doesn't exist on Windows and Cray Xt3/Catamount -// same for TIOCGWINSZ -#if defined(_WIN32) || defined(__LIBCATAMOUNT__) || \ - (defined(HAVE_GETPWNAM) && HAVE_GETPWNAM == 0) -# undef HAVE_GETPWNAM -# undef HAVE_TTY_INFO -#else -# define HAVE_GETPWNAM 1 -# define HAVE_TTY_INFO 1 -#endif - -#define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)" -#define VTK_URL_REGEX \ - "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/" \ - "(.+)?" - -#ifdef _MSC_VER -# include <sys/utime.h> -#else -# include <utime.h> -#endif - -// This is a hack to prevent warnings about these functions being -// declared but not referenced. -#if defined(__sgi) && !defined(__GNUC__) -# include <sys/termios.h> -namespace KWSYS_NAMESPACE { -class SystemToolsHack -{ -public: - enum - { - Ref1 = sizeof(cfgetospeed(0)), - Ref2 = sizeof(cfgetispeed(0)), - Ref3 = sizeof(tcgetattr(0, 0)), - Ref4 = sizeof(tcsetattr(0, 0, 0)), - Ref5 = sizeof(cfsetospeed(0, 0)), - Ref6 = sizeof(cfsetispeed(0, 0)) - }; -}; -} -#endif - -#if defined(_WIN32) && \ - (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || \ - defined(__MINGW32__)) -# include <direct.h> -# include <io.h> -# define _unlink unlink -#endif - -/* The maximum length of a file name. */ -#if defined(PATH_MAX) -# define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX -#elif defined(MAXPATHLEN) -# define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN -#else -# define KWSYS_SYSTEMTOOLS_MAXPATH 16384 -#endif -#if defined(__WATCOMC__) -# include <direct.h> -# define _mkdir mkdir -# define _rmdir rmdir -# define _getcwd getcwd -# define _chdir chdir -#endif - -#if defined(__BEOS__) && !defined(__ZETA__) -# include <be/kernel/OS.h> -# include <be/storage/Path.h> - -// BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. -static inline void usleep(unsigned int msec) -{ - ::snooze(msec); -} - -// BeOS 5 also doesn't have realpath(), but its C++ API offers something close. -static inline char* realpath(const char* path, char* resolved_path) -{ - const size_t maxlen = KWSYS_SYSTEMTOOLS_MAXPATH; - snprintf(resolved_path, maxlen, "%s", path); - BPath normalized(resolved_path, nullptr, true); - const char* resolved = normalized.Path(); - if (resolved != nullptr) // nullptr == No such file. - { - if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen) { - return resolved_path; - } - } - return nullptr; // something went wrong. -} -#endif - -#ifdef _WIN32 -static time_t windows_filetime_to_posix_time(const FILETIME& ft) -{ - LARGE_INTEGER date; - date.HighPart = ft.dwHighDateTime; - date.LowPart = ft.dwLowDateTime; - - // removes the diff between 1970 and 1601 - date.QuadPart -= ((LONGLONG)(369 * 365 + 89) * 24 * 3600 * 10000000); - - // converts back from 100-nanoseconds to seconds - return date.QuadPart / 10000000; -} -#endif - -#ifdef KWSYS_WINDOWS_DIRS -# include <wctype.h> - -inline int Mkdir(const std::string& dir) -{ - return _wmkdir( - KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str()); -} -inline int Rmdir(const std::string& dir) -{ - return _wrmdir( - KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str()); -} -inline const char* Getcwd(char* buf, unsigned int len) -{ - std::vector<wchar_t> w_buf(len); - if (_wgetcwd(&w_buf[0], len)) { - size_t nlen = kwsysEncoding_wcstombs(buf, &w_buf[0], len); - if (nlen == static_cast<size_t>(-1)) { - return 0; - } - if (nlen < len) { - // make sure the drive letter is capital - if (nlen > 1 && buf[1] == ':') { - buf[0] = toupper(buf[0]); - } - return buf; - } - } - return 0; -} -inline int Chdir(const std::string& dir) -{ -# if defined(__BORLANDC__) - return chdir(dir.c_str()); -# else - return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); -# endif -} -inline void Realpath(const std::string& path, std::string& resolved_path, - std::string* errorMessage = 0) -{ - std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path); - wchar_t* ptemp; - wchar_t fullpath[MAX_PATH]; - DWORD bufferLen = GetFullPathNameW( - tmp.c_str(), sizeof(fullpath) / sizeof(fullpath[0]), fullpath, &ptemp); - if (bufferLen < sizeof(fullpath) / sizeof(fullpath[0])) { - resolved_path = KWSYS_NAMESPACE::Encoding::ToNarrow(fullpath); - KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path); - } else if (errorMessage) { - if (bufferLen) { - *errorMessage = "Destination path buffer size too small."; - } else 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."; - } - - resolved_path = ""; - } else { - resolved_path = path; - } -} -#else -# include <sys/types.h> - -# include <fcntl.h> -# include <unistd.h> -inline int Mkdir(const std::string& dir) -{ - return mkdir(dir.c_str(), 00777); -} -inline int Rmdir(const std::string& dir) -{ - return rmdir(dir.c_str()); -} -inline const char* Getcwd(char* buf, unsigned int len) -{ - return getcwd(buf, len); -} - -inline int Chdir(const std::string& dir) -{ - return chdir(dir.c_str()); -} -inline void Realpath(const std::string& path, std::string& resolved_path, - std::string* errorMessage = nullptr) -{ - char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH]; - - errno = 0; - char* ret = realpath(path.c_str(), resolved_name); - if (ret) { - resolved_path = ret; - } else if (errorMessage) { - if (errno) { - *errorMessage = strerror(errno); - } else { - *errorMessage = "Unknown error."; - } - - resolved_path = ""; - } else { - // if path resolution fails, return what was passed in - resolved_path = path; - } -} -#endif - -#if !defined(_WIN32) && defined(__COMO__) -// Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE. -extern "C" { -extern FILE* popen(__const char* __command, __const char* __modes) __THROW; -extern int pclose(FILE* __stream) __THROW; -extern char* realpath(__const char* __restrict __name, - char* __restrict __resolved) __THROW; -extern char* strdup(__const char* __s) __THROW; -extern int putenv(char* __string) __THROW; -} -#endif - -namespace KWSYS_NAMESPACE { - -double SystemTools::GetTime(void) -{ -#if defined(_WIN32) && !defined(__CYGWIN__) - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - return (429.4967296 * ft.dwHighDateTime + 0.0000001 * ft.dwLowDateTime - - 11644473600.0); -#else - struct timeval t; - gettimeofday(&t, nullptr); - return 1.0 * double(t.tv_sec) + 0.000001 * double(t.tv_usec); -#endif -} - -/* Type of character storing the environment. */ -#if defined(_WIN32) -typedef wchar_t envchar; -#else -typedef char envchar; -#endif - -/* Order by environment key only (VAR from VAR=VALUE). */ -struct kwsysEnvCompare -{ - bool operator()(const envchar* l, const envchar* r) const - { -#if defined(_WIN32) - const wchar_t* leq = wcschr(l, L'='); - const wchar_t* req = wcschr(r, L'='); - size_t llen = leq ? (leq - l) : wcslen(l); - size_t rlen = req ? (req - r) : wcslen(r); - if (llen == rlen) { - return wcsncmp(l, r, llen) < 0; - } else { - return wcscmp(l, r) < 0; - } -#else - const char* leq = strchr(l, '='); - const char* req = strchr(r, '='); - size_t llen = leq ? static_cast<size_t>(leq - l) : strlen(l); - size_t rlen = req ? static_cast<size_t>(req - r) : strlen(r); - if (llen == rlen) { - return strncmp(l, r, llen) < 0; - } else { - return strcmp(l, r) < 0; - } -#endif - } -}; - -class kwsysEnvSet : public std::set<const envchar*, kwsysEnvCompare> -{ -public: - class Free - { - const envchar* Env; - - public: - Free(const envchar* env) - : Env(env) - { - } - ~Free() { free(const_cast<envchar*>(this->Env)); } - - Free(const Free&) = delete; - Free& operator=(const Free&) = delete; - }; - - const envchar* Release(const envchar* env) - { - const envchar* old = nullptr; - iterator i = this->find(env); - if (i != this->end()) { - old = *i; - this->erase(i); - } - return old; - } -}; - -#ifdef _WIN32 -struct SystemToolsPathCaseCmp -{ - bool operator()(std::string const& l, std::string const& r) const - { -# ifdef _MSC_VER - return _stricmp(l.c_str(), r.c_str()) < 0; -# elif defined(__GNUC__) - return strcasecmp(l.c_str(), r.c_str()) < 0; -# else - return SystemTools::Strucmp(l.c_str(), r.c_str()) < 0; -# endif - } -}; -#endif - -/** - * SystemTools static variables singleton class. - */ -class SystemToolsStatic -{ -public: - typedef std::map<std::string, std::string> StringMap; -#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP - /** - * Path translation table from dir to refdir - * Each time 'dir' will be found it will be replace by 'refdir' - */ - StringMap TranslationMap; -#endif -#ifdef _WIN32 - static std::string GetCasePathName(std::string const& pathIn); - static std::string GetActualCaseForPathCached(std::string const& path); - static const char* GetEnvBuffered(const char* key); - std::map<std::string, std::string, SystemToolsPathCaseCmp> PathCaseMap; - std::map<std::string, std::string> EnvMap; -#endif -#ifdef __CYGWIN__ - StringMap Cyg2Win32Map; -#endif - - /** - * Actual implementation of ReplaceString. - */ - static void ReplaceString(std::string& source, const char* replace, - size_t replaceSize, const std::string& with); - - /** - * Actual implementation of FileIsFullPath. - */ - static bool FileIsFullPath(const char*, size_t); - - /** - * Find a filename (file or directory) in the system PATH, with - * optional extra paths. - */ - static std::string FindName( - const std::string& name, - const std::vector<std::string>& path = std::vector<std::string>(), - bool no_system_path = false); -}; - -#ifdef _WIN32 -std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn) -{ - std::string casePath; - - // First check if the file is relative. We don't fix relative paths since the - // real case depends on the root directory and the given path fragment may - // have meaning elsewhere in the project. - if (!SystemTools::FileIsFullPath(pathIn)) { - // This looks unnecessary, but it allows for the return value optimization - // since all return paths return the same local variable. - casePath = pathIn; - return casePath; - } - - std::vector<std::string> path_components; - SystemTools::SplitPath(pathIn, path_components); - - // Start with root component. - std::vector<std::string>::size_type idx = 0; - casePath = path_components[idx++]; - // make sure drive letter is always upper case - if (casePath.size() > 1 && casePath[1] == ':') { - casePath[0] = toupper(casePath[0]); - } - const char* sep = ""; - - // If network path, fill casePath with server/share so FindFirstFile - // will work after that. Maybe someday call other APIs to get - // actual case of servers and shares. - if (path_components.size() > 2 && path_components[0] == "//") { - casePath += path_components[idx++]; - casePath += "/"; - casePath += path_components[idx++]; - sep = "/"; - } - - // Convert case of all components that exist. - bool converting = true; - for (; idx < path_components.size(); idx++) { - casePath += sep; - sep = "/"; - - if (converting) { - // If path component contains wildcards, we skip matching - // because these filenames are not allowed on windows, - // and we do not want to match a different file. - if (path_components[idx].find('*') != std::string::npos || - path_components[idx].find('?') != std::string::npos) { - converting = false; - } else { - std::string test_str = casePath; - test_str += path_components[idx]; - WIN32_FIND_DATAW findData; - HANDLE hFind = - ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData); - if (INVALID_HANDLE_VALUE != hFind) { - path_components[idx] = Encoding::ToNarrow(findData.cFileName); - ::FindClose(hFind); - } else { - converting = false; - } - } - } - - casePath += path_components[idx]; - } - return casePath; -} - -std::string SystemToolsStatic::GetActualCaseForPathCached(std::string const& p) -{ - // Check to see if actual case has already been called - // for this path, and the result is stored in the PathCaseMap - auto& pcm = SystemTools::Statics->PathCaseMap; - { - auto itr = pcm.find(p); - if (itr != pcm.end()) { - return itr->second; - } - } - std::string casePath = SystemToolsStatic::GetCasePathName(p); - if (casePath.size() <= MAX_PATH) { - pcm[p] = casePath; - } - return casePath; -} -#endif - -// adds the elements of the env variable path to the arg passed in -void SystemTools::GetPath(std::vector<std::string>& path, const char* env) -{ - size_t const old_size = path.size(); -#if defined(_WIN32) && !defined(__CYGWIN__) - const char pathSep = ';'; -#else - const char pathSep = ':'; -#endif - if (!env) { - env = "PATH"; - } - std::string pathEnv; - if (!SystemTools::GetEnv(env, pathEnv)) { - return; - } - - // A hack to make the below algorithm work. - if (!pathEnv.empty() && pathEnv.back() != pathSep) { - pathEnv += pathSep; - } - std::string::size_type start = 0; - bool done = false; - while (!done) { - std::string::size_type endpos = pathEnv.find(pathSep, start); - if (endpos != std::string::npos) { - path.push_back(pathEnv.substr(start, endpos - start)); - start = endpos + 1; - } else { - done = true; - } - } - for (std::vector<std::string>::iterator i = path.begin() + old_size; - i != path.end(); ++i) { - SystemTools::ConvertToUnixSlashes(*i); - } -} - -#if defined(_WIN32) -const char* SystemToolsStatic::GetEnvBuffered(const char* key) -{ - std::string env; - if (SystemTools::GetEnv(key, env)) { - std::string& menv = SystemTools::Statics->EnvMap[key]; - if (menv != env) { - menv = std::move(env); - } - return menv.c_str(); - } - return nullptr; -} -#endif - -const char* SystemTools::GetEnv(const char* key) -{ -#if defined(_WIN32) - return SystemToolsStatic::GetEnvBuffered(key); -#else - return getenv(key); -#endif -} - -const char* SystemTools::GetEnv(const std::string& key) -{ -#if defined(_WIN32) - return SystemToolsStatic::GetEnvBuffered(key.c_str()); -#else - return getenv(key.c_str()); -#endif -} - -bool SystemTools::GetEnv(const char* key, std::string& result) -{ -#if defined(_WIN32) - const std::wstring wkey = Encoding::ToWide(key); - const wchar_t* wv = _wgetenv(wkey.c_str()); - if (wv) { - result = Encoding::ToNarrow(wv); - return true; - } -#else - const char* v = getenv(key); - if (v) { - result = v; - return true; - } -#endif - return false; -} - -bool SystemTools::GetEnv(const std::string& key, std::string& result) -{ - return SystemTools::GetEnv(key.c_str(), result); -} - -bool SystemTools::HasEnv(const char* key) -{ -#if defined(_WIN32) - const std::wstring wkey = Encoding::ToWide(key); - const wchar_t* v = _wgetenv(wkey.c_str()); -#else - const char* v = getenv(key); -#endif - return v != nullptr; -} - -bool SystemTools::HasEnv(const std::string& key) -{ - return SystemTools::HasEnv(key.c_str()); -} - -#if KWSYS_CXX_HAS_UNSETENV -/* unsetenv("A") removes A from the environment. - On older platforms it returns void instead of int. */ -static int kwsysUnPutEnv(const std::string& env) -{ - size_t pos = env.find('='); - if (pos != std::string::npos) { - std::string name = env.substr(0, pos); - unsetenv(name.c_str()); - } else { - unsetenv(env.c_str()); - } - return 0; -} - -#elif defined(__CYGWIN__) || defined(__GLIBC__) -/* putenv("A") removes A from the environment. It must not put the - memory in the environment because it does not have any "=" syntax. */ -static int kwsysUnPutEnv(const std::string& env) -{ - int err = 0; - size_t pos = env.find('='); - size_t const len = pos == std::string::npos ? env.size() : pos; - size_t const sz = len + 1; - char local_buf[256]; - char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf; - if (!buf) { - return -1; - } - strncpy(buf, env.c_str(), len); - buf[len] = 0; - if (putenv(buf) < 0 && errno != EINVAL) { - err = errno; - } - if (buf != local_buf) { - free(buf); - } - if (err) { - errno = err; - return -1; - } - return 0; -} - -#elif defined(_WIN32) -/* putenv("A=") places "A=" in the environment, which is as close to - removal as we can get with the putenv API. We have to leak the - most recent value placed in the environment for each variable name - on program exit in case exit routines access it. */ - -static kwsysEnvSet kwsysUnPutEnvSet; - -static int kwsysUnPutEnv(std::string const& env) -{ - std::wstring wEnv = Encoding::ToWide(env); - size_t const pos = wEnv.find('='); - size_t const len = pos == std::string::npos ? wEnv.size() : pos; - wEnv.resize(len + 1, L'='); - wchar_t* newEnv = _wcsdup(wEnv.c_str()); - if (!newEnv) { - return -1; - } - kwsysEnvSet::Free oldEnv(kwsysUnPutEnvSet.Release(newEnv)); - kwsysUnPutEnvSet.insert(newEnv); - return _wputenv(newEnv); -} - -#else -/* Manipulate the "environ" global directly. */ -static int kwsysUnPutEnv(const std::string& env) -{ - size_t pos = env.find('='); - size_t const len = pos == std::string::npos ? env.size() : pos; - int in = 0; - int out = 0; - while (environ[in]) { - if (strlen(environ[in]) > len && environ[in][len] == '=' && - strncmp(env.c_str(), environ[in], len) == 0) { - ++in; - } else { - environ[out++] = environ[in++]; - } - } - while (out < in) { - environ[out++] = 0; - } - return 0; -} -#endif - -#if KWSYS_CXX_HAS_SETENV - -/* setenv("A", "B", 1) will set A=B in the environment and makes its - own copies of the strings. */ -bool SystemTools::PutEnv(const std::string& env) -{ - size_t pos = env.find('='); - if (pos != std::string::npos) { - std::string name = env.substr(0, pos); - return setenv(name.c_str(), env.c_str() + pos + 1, 1) == 0; - } else { - return kwsysUnPutEnv(env) == 0; - } -} - -bool SystemTools::UnPutEnv(const std::string& env) -{ - return kwsysUnPutEnv(env) == 0; -} - -#else - -/* putenv("A=B") will set A=B in the environment. Most putenv implementations - put their argument directly in the environment. They never free the memory - on program exit. Keep an active set of pointers to memory we allocate and - pass to putenv, one per environment key. At program exit remove any - environment values that may still reference memory we allocated. Then free - the memory. This will not affect any environment values we never set. */ - -# ifdef __INTEL_COMPILER -# pragma warning disable 444 /* base has non-virtual destructor */ -# endif - -class kwsysEnv : public kwsysEnvSet -{ -public: - ~kwsysEnv() - { - for (iterator i = this->begin(); i != this->end(); ++i) { -# if defined(_WIN32) - const std::string s = Encoding::ToNarrow(*i); - kwsysUnPutEnv(s); -# else - kwsysUnPutEnv(*i); -# endif - free(const_cast<envchar*>(*i)); - } - } - bool Put(const char* env) - { -# if defined(_WIN32) - const std::wstring wEnv = Encoding::ToWide(env); - wchar_t* newEnv = _wcsdup(wEnv.c_str()); -# else - char* newEnv = strdup(env); -# endif - Free oldEnv(this->Release(newEnv)); - this->insert(newEnv); -# if defined(_WIN32) - return _wputenv(newEnv) == 0; -# else - return putenv(newEnv) == 0; -# endif - } - bool UnPut(const char* env) - { -# if defined(_WIN32) - const std::wstring wEnv = Encoding::ToWide(env); - Free oldEnv(this->Release(wEnv.c_str())); -# else - Free oldEnv(this->Release(env)); -# endif - return kwsysUnPutEnv(env) == 0; - } -}; - -static kwsysEnv kwsysEnvInstance; - -bool SystemTools::PutEnv(const std::string& env) -{ - return kwsysEnvInstance.Put(env.c_str()); -} - -bool SystemTools::UnPutEnv(const std::string& env) -{ - return kwsysEnvInstance.UnPut(env.c_str()); -} - -#endif - -const char* SystemTools::GetExecutableExtension() -{ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS) - return ".exe"; -#else - return ""; -#endif -} - -FILE* SystemTools::Fopen(const std::string& file, const char* mode) -{ -#ifdef _WIN32 - return _wfopen(Encoding::ToWindowsExtendedPath(file).c_str(), - Encoding::ToWide(mode).c_str()); -#else - return fopen(file.c_str(), mode); -#endif -} - -bool SystemTools::MakeDirectory(const char* path, const mode_t* mode) -{ - if (!path) { - return false; - } - return SystemTools::MakeDirectory(std::string(path), mode); -} - -bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode) -{ - if (SystemTools::PathExists(path)) { - return SystemTools::FileIsDirectory(path); - } - if (path.empty()) { - return false; - } - std::string dir = path; - SystemTools::ConvertToUnixSlashes(dir); - - std::string::size_type pos = 0; - std::string topdir; - while ((pos = dir.find('/', pos)) != std::string::npos) { - topdir = dir.substr(0, pos); - - if (Mkdir(topdir) == 0 && mode != nullptr) { - SystemTools::SetPermissions(topdir, *mode); - } - - ++pos; - } - topdir = dir; - if (Mkdir(topdir) != 0) { - // There is a bug in the Borland Run time library which makes MKDIR - // return EACCES when it should return EEXISTS - // if it is some other error besides directory exists - // then return false - if ((errno != EEXIST) -#ifdef __BORLANDC__ - && (errno != EACCES) -#endif - ) { - return false; - } - } else if (mode != nullptr) { - SystemTools::SetPermissions(topdir, *mode); - } - - return true; -} - -// replace replace with with as many times as it shows up in source. -// write the result into source. -void SystemTools::ReplaceString(std::string& source, - const std::string& replace, - const std::string& with) -{ - // do while hangs if replaceSize is 0 - if (replace.empty()) { - return; - } - - SystemToolsStatic::ReplaceString(source, replace.c_str(), replace.size(), - with); -} - -void SystemTools::ReplaceString(std::string& source, const char* replace, - const char* with) -{ - // do while hangs if replaceSize is 0 - if (!*replace) { - return; - } - - SystemToolsStatic::ReplaceString(source, replace, strlen(replace), - with ? with : ""); -} - -void SystemToolsStatic::ReplaceString(std::string& source, const char* replace, - size_t replaceSize, - const std::string& with) -{ - const char* src = source.c_str(); - char* searchPos = const_cast<char*>(strstr(src, replace)); - - // get out quick if string is not found - if (!searchPos) { - return; - } - - // perform replacements until done - char* orig = strdup(src); - char* currentPos = orig; - searchPos = searchPos - src + orig; - - // initialize the result - source.erase(source.begin(), source.end()); - do { - *searchPos = '\0'; - source += currentPos; - currentPos = searchPos + replaceSize; - // replace - source += with; - searchPos = strstr(currentPos, replace); - } while (searchPos); - - // copy any trailing text - source += currentPos; - free(orig); -} - -#if defined(_WIN32) && !defined(__CYGWIN__) - -# if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY) -# define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY -# define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY -# else -# define KWSYS_ST_KEY_WOW64_32KEY 0x0200 -# define KWSYS_ST_KEY_WOW64_64KEY 0x0100 -# endif - -static bool SystemToolsParseRegistryKey(const std::string& key, - HKEY& primaryKey, std::string& second, - std::string& valuename) -{ - std::string primary = key; - - size_t start = primary.find('\\'); - if (start == std::string::npos) { - return false; - } - - size_t valuenamepos = primary.find(';'); - if (valuenamepos != std::string::npos) { - valuename = primary.substr(valuenamepos + 1); - } - - second = primary.substr(start + 1, valuenamepos - start - 1); - primary = primary.substr(0, start); - - if (primary == "HKEY_CURRENT_USER") { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") { - primaryKey = HKEY_USERS; - } - - return true; -} - -static DWORD SystemToolsMakeRegistryMode(DWORD mode, - SystemTools::KeyWOW64 view) -{ - // only add the modes when on a system that supports Wow64. - static FARPROC wow64p = - GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process"); - if (wow64p == nullptr) { - return mode; - } - - if (view == SystemTools::KeyWOW64_32) { - return mode | KWSYS_ST_KEY_WOW64_32KEY; - } else if (view == SystemTools::KeyWOW64_64) { - return mode | KWSYS_ST_KEY_WOW64_64KEY; - } - return mode; -} -#endif - -#if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::GetRegistrySubKeys(const std::string& key, - std::vector<std::string>& subkeys, - KeyWOW64 view) -{ - HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; - std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { - return false; - } - - HKEY hKey; - if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, - SystemToolsMakeRegistryMode(KEY_READ, view), - &hKey) != ERROR_SUCCESS) { - return false; - } else { - wchar_t name[1024]; - DWORD dwNameSize = sizeof(name) / sizeof(name[0]); - - DWORD i = 0; - while (RegEnumKeyW(hKey, i, name, dwNameSize) == ERROR_SUCCESS) { - subkeys.push_back(Encoding::ToNarrow(name)); - ++i; - } - - RegCloseKey(hKey); - } - - return true; -} -#else -bool SystemTools::GetRegistrySubKeys(const std::string&, - std::vector<std::string>&, KeyWOW64) -{ - return false; -} -#endif - -// Read a registry value. -// Example : -// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath -// => will return the data of the "default" value of the key -// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root -// => will return the data of the "Root" value of the key - -#if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::ReadRegistryValue(const std::string& key, std::string& value, - KeyWOW64 view) -{ - bool valueset = false; - HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; - std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { - return false; - } - - HKEY hKey; - if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, - SystemToolsMakeRegistryMode(KEY_READ, view), - &hKey) != ERROR_SUCCESS) { - return false; - } else { - DWORD dwType, dwSize; - dwSize = 1023; - wchar_t data[1024]; - if (RegQueryValueExW(hKey, Encoding::ToWide(valuename).c_str(), nullptr, - &dwType, (BYTE*)data, &dwSize) == ERROR_SUCCESS) { - if (dwType == REG_SZ) { - value = Encoding::ToNarrow(data); - valueset = true; - } else if (dwType == REG_EXPAND_SZ) { - wchar_t expanded[1024]; - DWORD dwExpandedSize = sizeof(expanded) / sizeof(expanded[0]); - if (ExpandEnvironmentStringsW(data, expanded, dwExpandedSize)) { - value = Encoding::ToNarrow(expanded); - valueset = true; - } - } - } - - RegCloseKey(hKey); - } - - return valueset; -} -#else -bool SystemTools::ReadRegistryValue(const std::string&, std::string&, KeyWOW64) -{ - return false; -} -#endif - -// Write a registry value. -// Example : -// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath -// => will set the data of the "default" value of the key -// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root -// => will set the data of the "Root" value of the key - -#if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::WriteRegistryValue(const std::string& key, - const std::string& value, KeyWOW64 view) -{ - HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; - std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { - return false; - } - - HKEY hKey; - DWORD dwDummy; - wchar_t lpClass[] = L""; - if (RegCreateKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, lpClass, - REG_OPTION_NON_VOLATILE, - SystemToolsMakeRegistryMode(KEY_WRITE, view), nullptr, - &hKey, &dwDummy) != ERROR_SUCCESS) { - return false; - } - - std::wstring wvalue = Encoding::ToWide(value); - if (RegSetValueExW(hKey, Encoding::ToWide(valuename).c_str(), 0, REG_SZ, - (CONST BYTE*)wvalue.c_str(), - (DWORD)(sizeof(wchar_t) * (wvalue.size() + 1))) == - ERROR_SUCCESS) { - return true; - } - return false; -} -#else -bool SystemTools::WriteRegistryValue(const std::string&, const std::string&, - KeyWOW64) -{ - return false; -} -#endif - -// Delete a registry value. -// Example : -// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath -// => will delete the data of the "default" value of the key -// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root -// => will delete the data of the "Root" value of the key - -#if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::DeleteRegistryValue(const std::string& key, KeyWOW64 view) -{ - HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; - std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { - return false; - } - - HKEY hKey; - if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, - SystemToolsMakeRegistryMode(KEY_WRITE, view), - &hKey) != ERROR_SUCCESS) { - return false; - } else { - if (RegDeleteValue(hKey, (LPTSTR)valuename.c_str()) == ERROR_SUCCESS) { - RegCloseKey(hKey); - return true; - } - } - return false; -} -#else -bool SystemTools::DeleteRegistryValue(const std::string&, KeyWOW64) -{ - return false; -} -#endif - -bool SystemTools::SameFile(const std::string& file1, const std::string& file2) -{ -#ifdef _WIN32 - HANDLE hFile1, hFile2; - - hFile1 = - CreateFileW(Encoding::ToWide(file1).c_str(), GENERIC_READ, FILE_SHARE_READ, - nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - hFile2 = - CreateFileW(Encoding::ToWide(file2).c_str(), GENERIC_READ, FILE_SHARE_READ, - nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE) { - if (hFile1 != INVALID_HANDLE_VALUE) { - CloseHandle(hFile1); - } - if (hFile2 != INVALID_HANDLE_VALUE) { - CloseHandle(hFile2); - } - return false; - } - - BY_HANDLE_FILE_INFORMATION fiBuf1; - BY_HANDLE_FILE_INFORMATION fiBuf2; - GetFileInformationByHandle(hFile1, &fiBuf1); - GetFileInformationByHandle(hFile2, &fiBuf2); - CloseHandle(hFile1); - CloseHandle(hFile2); - return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber && - fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh && - fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow); -#else - struct stat fileStat1, fileStat2; - if (stat(file1.c_str(), &fileStat1) == 0 && - stat(file2.c_str(), &fileStat2) == 0) { - // see if the files are the same file - // check the device inode and size - if (memcmp(&fileStat2.st_dev, &fileStat1.st_dev, - sizeof(fileStat1.st_dev)) == 0 && - memcmp(&fileStat2.st_ino, &fileStat1.st_ino, - sizeof(fileStat1.st_ino)) == 0 && - fileStat2.st_size == fileStat1.st_size) { - return true; - } - } - return false; -#endif -} - -bool SystemTools::PathExists(const std::string& path) -{ - if (path.empty()) { - return false; - } -#if defined(__CYGWIN__) - // Convert path to native windows path if possible. - char winpath[MAX_PATH]; - if (SystemTools::PathCygwinToWin32(path.c_str(), winpath)) { - return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES); - } - struct stat st; - return lstat(path.c_str(), &st) == 0; -#elif defined(_WIN32) - return (GetFileAttributesW(Encoding::ToWindowsExtendedPath(path).c_str()) != - INVALID_FILE_ATTRIBUTES); -#else - struct stat st; - return lstat(path.c_str(), &st) == 0; -#endif -} - -bool SystemTools::FileExists(const char* filename) -{ - if (!filename) { - return false; - } - return SystemTools::FileExists(std::string(filename)); -} - -bool SystemTools::FileExists(const std::string& filename) -{ - if (filename.empty()) { - return false; - } -#if defined(__CYGWIN__) - // Convert filename to native windows path if possible. - char winpath[MAX_PATH]; - if (SystemTools::PathCygwinToWin32(filename.c_str(), winpath)) { - return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES); - } - return access(filename.c_str(), R_OK) == 0; -#elif defined(_WIN32) - DWORD attr = - GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()); - if (attr == INVALID_FILE_ATTRIBUTES) { - return false; - } - - if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { - // Using 0 instead of GENERIC_READ as it allows reading of file attributes - // even if we do not have permission to read the file itself - HANDLE handle = - CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), 0, 0, - nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - - if (handle == INVALID_HANDLE_VALUE) { - return false; - } - - CloseHandle(handle); - } - - return true; -#else -// SCO OpenServer 5.0.7/3.2's command has 711 permission. -# if defined(_SCO_DS) - return access(filename.c_str(), F_OK) == 0; -# else - return access(filename.c_str(), R_OK) == 0; -# endif -#endif -} - -bool SystemTools::FileExists(const char* filename, bool isFile) -{ - if (!filename) { - return false; - } - return SystemTools::FileExists(std::string(filename), isFile); -} - -bool SystemTools::FileExists(const std::string& filename, bool isFile) -{ - if (SystemTools::FileExists(filename)) { - // If isFile is set return not FileIsDirectory, - // so this will only be true if it is a file - return !isFile || !SystemTools::FileIsDirectory(filename); - } - return false; -} - -bool SystemTools::TestFileAccess(const char* filename, - TestFilePermissions permissions) -{ - if (!filename) { - return false; - } - return SystemTools::TestFileAccess(std::string(filename), permissions); -} - -bool SystemTools::TestFileAccess(const std::string& filename, - TestFilePermissions permissions) -{ - if (filename.empty()) { - return false; - } -#if defined(_WIN32) && !defined(__CYGWIN__) - // If execute set, change to read permission (all files on Windows - // are executable if they are readable). The CRT will always fail - // if you pass an execute bit. - if (permissions & TEST_FILE_EXECUTE) { - permissions &= ~TEST_FILE_EXECUTE; - permissions |= TEST_FILE_READ; - } - return _waccess(Encoding::ToWindowsExtendedPath(filename).c_str(), - permissions) == 0; -#else - return access(filename.c_str(), permissions) == 0; -#endif -} - -int SystemTools::Stat(const char* path, SystemTools::Stat_t* buf) -{ - if (!path) { - errno = EFAULT; - return -1; - } - return SystemTools::Stat(std::string(path), buf); -} - -int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf) -{ - if (path.empty()) { - errno = ENOENT; - return -1; - } -#if defined(_WIN32) && !defined(__CYGWIN__) - // Ideally we should use Encoding::ToWindowsExtendedPath to support - // long paths, but _wstat64 rejects paths with '?' in them, thinking - // they are wildcards. - std::wstring const& wpath = Encoding::ToWide(path); -# if defined(__BORLANDC__) - return _wstati64(wpath.c_str(), buf); -# else - return _wstat64(wpath.c_str(), buf); -# endif -#else - return stat(path.c_str(), buf); -#endif -} - -#ifdef __CYGWIN__ -bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path) -{ - auto itr = SystemTools::Statics->Cyg2Win32Map.find(path); - if (itr != SystemTools::Statics->Cyg2Win32Map.end()) { - strncpy(win32_path, itr->second.c_str(), MAX_PATH); - } else { - if (cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, win32_path, MAX_PATH) != - 0) { - win32_path[0] = 0; - } - SystemTools::Statics->Cyg2Win32Map.insert( - SystemToolsStatic::StringMap::value_type(path, win32_path)); - } - return win32_path[0] != 0; -} -#endif - -bool SystemTools::Touch(const std::string& filename, bool create) -{ - if (!SystemTools::PathExists(filename)) { - if (create) { - FILE* file = Fopen(filename, "a+b"); - if (file) { - fclose(file); - return true; - } - return false; - } else { - return true; - } - } -#if defined(_WIN32) && !defined(__CYGWIN__) - HANDLE h = CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), - FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); - if (!h) { - return false; - } - FILETIME mtime; - GetSystemTimeAsFileTime(&mtime); - if (!SetFileTime(h, 0, 0, &mtime)) { - CloseHandle(h); - return false; - } - 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; - } -#else - // fall back to utimes - if (utimes(filename.c_str(), nullptr) < 0) { - return false; - } -#endif - return true; -} - -bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, - int* result) -{ - // Default to same time. - *result = 0; -#if !defined(_WIN32) || defined(__CYGWIN__) - // POSIX version. Use stat function to get file modification time. - struct stat s1; - if (stat(f1.c_str(), &s1) != 0) { - return false; - } - struct stat s2; - if (stat(f2.c_str(), &s2) != 0) { - return false; - } -# if KWSYS_CXX_STAT_HAS_ST_MTIM - // Compare using nanosecond resolution. - if (s1.st_mtim.tv_sec < s2.st_mtim.tv_sec) { - *result = -1; - } else if (s1.st_mtim.tv_sec > s2.st_mtim.tv_sec) { - *result = 1; - } else if (s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec) { - *result = -1; - } else if (s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec) { - *result = 1; - } -# elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC - // Compare using nanosecond resolution. - if (s1.st_mtimespec.tv_sec < s2.st_mtimespec.tv_sec) { - *result = -1; - } else if (s1.st_mtimespec.tv_sec > s2.st_mtimespec.tv_sec) { - *result = 1; - } else if (s1.st_mtimespec.tv_nsec < s2.st_mtimespec.tv_nsec) { - *result = -1; - } else if (s1.st_mtimespec.tv_nsec > s2.st_mtimespec.tv_nsec) { - *result = 1; - } -# else - // Compare using 1 second resolution. - if (s1.st_mtime < s2.st_mtime) { - *result = -1; - } else if (s1.st_mtime > s2.st_mtime) { - *result = 1; - } -# endif -#else - // Windows version. Get the modification time from extended file attributes. - WIN32_FILE_ATTRIBUTE_DATA f1d; - WIN32_FILE_ATTRIBUTE_DATA f2d; - if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(), - GetFileExInfoStandard, &f1d)) { - return false; - } - if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(), - GetFileExInfoStandard, &f2d)) { - return false; - } - - // Compare the file times using resolution provided by system call. - *result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime); -#endif - return true; -} - -// Return a capitalized string (i.e the first letter is uppercased, all other -// are lowercased) -std::string SystemTools::Capitalized(const std::string& s) -{ - std::string n; - if (s.empty()) { - return n; - } - n.resize(s.size()); - n[0] = static_cast<std::string::value_type>(toupper(s[0])); - for (size_t i = 1; i < s.size(); i++) { - n[i] = static_cast<std::string::value_type>(tolower(s[i])); - } - return n; -} - -// Return capitalized words -std::string SystemTools::CapitalizedWords(const std::string& s) -{ - std::string n(s); - for (size_t i = 0; i < s.size(); i++) { -#if defined(_MSC_VER) && defined(_MT) && defined(_DEBUG) - // MS has an assert that will fail if s[i] < 0; setting - // LC_CTYPE using setlocale() does *not* help. Painful. - if ((int)s[i] >= 0 && isalpha(s[i]) && - (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1])))) -#else - if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1]))) -#endif - { - n[i] = static_cast<std::string::value_type>(toupper(s[i])); - } - } - return n; -} - -// Return uncapitalized words -std::string SystemTools::UnCapitalizedWords(const std::string& s) -{ - std::string n(s); - for (size_t i = 0; i < s.size(); i++) { -#if defined(_MSC_VER) && defined(_MT) && defined(_DEBUG) - // MS has an assert that will fail if s[i] < 0; setting - // LC_CTYPE using setlocale() does *not* help. Painful. - if ((int)s[i] >= 0 && isalpha(s[i]) && - (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1])))) -#else - if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1]))) -#endif - { - n[i] = static_cast<std::string::value_type>(tolower(s[i])); - } - } - return n; -} - -// only works for words with at least two letters -std::string SystemTools::AddSpaceBetweenCapitalizedWords(const std::string& s) -{ - std::string n; - if (!s.empty()) { - n.reserve(s.size()); - n += s[0]; - for (size_t i = 1; i < s.size(); i++) { - if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1])) { - n += ' '; - } - n += s[i]; - } - } - return n; -} - -char* SystemTools::AppendStrings(const char* str1, const char* str2) -{ - if (!str1) { - return SystemTools::DuplicateString(str2); - } - if (!str2) { - return SystemTools::DuplicateString(str1); - } - size_t len1 = strlen(str1); - char* newstr = new char[len1 + strlen(str2) + 1]; - if (!newstr) { - return nullptr; - } - strcpy(newstr, str1); - strcat(newstr + len1, str2); - return newstr; -} - -char* SystemTools::AppendStrings(const char* str1, const char* str2, - const char* str3) -{ - if (!str1) { - return SystemTools::AppendStrings(str2, str3); - } - if (!str2) { - return SystemTools::AppendStrings(str1, str3); - } - if (!str3) { - return SystemTools::AppendStrings(str1, str2); - } - - size_t len1 = strlen(str1), len2 = strlen(str2); - char* newstr = new char[len1 + len2 + strlen(str3) + 1]; - if (!newstr) { - return nullptr; - } - strcpy(newstr, str1); - strcat(newstr + len1, str2); - strcat(newstr + len1 + len2, str3); - return newstr; -} - -// Return a lower case string -std::string SystemTools::LowerCase(const std::string& s) -{ - std::string n; - n.resize(s.size()); - for (size_t i = 0; i < s.size(); i++) { - n[i] = static_cast<std::string::value_type>(tolower(s[i])); - } - return n; -} - -// Return a lower case string -std::string SystemTools::UpperCase(const std::string& s) -{ - std::string n; - n.resize(s.size()); - for (size_t i = 0; i < s.size(); i++) { - n[i] = static_cast<std::string::value_type>(toupper(s[i])); - } - return n; -} - -// Count char in string -size_t SystemTools::CountChar(const char* str, char c) -{ - size_t count = 0; - - if (str) { - while (*str) { - if (*str == c) { - ++count; - } - ++str; - } - } - return count; -} - -// Remove chars in string -char* SystemTools::RemoveChars(const char* str, const char* toremove) -{ - if (!str) { - return nullptr; - } - char* clean_str = new char[strlen(str) + 1]; - char* ptr = clean_str; - while (*str) { - const char* str2 = toremove; - while (*str2 && *str != *str2) { - ++str2; - } - if (!*str2) { - *ptr++ = *str; - } - ++str; - } - *ptr = '\0'; - return clean_str; -} - -// Remove chars in string -char* SystemTools::RemoveCharsButUpperHex(const char* str) -{ - if (!str) { - return nullptr; - } - char* clean_str = new char[strlen(str) + 1]; - char* ptr = clean_str; - while (*str) { - if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'F')) { - *ptr++ = *str; - } - ++str; - } - *ptr = '\0'; - return clean_str; -} - -// Replace chars in string -char* SystemTools::ReplaceChars(char* str, const char* toreplace, - char replacement) -{ - if (str) { - char* ptr = str; - while (*ptr) { - const char* ptr2 = toreplace; - while (*ptr2) { - if (*ptr == *ptr2) { - *ptr = replacement; - } - ++ptr2; - } - ++ptr; - } - } - return str; -} - -// Returns if string starts with another string -bool SystemTools::StringStartsWith(const char* str1, const char* str2) -{ - if (!str1 || !str2) { - return false; - } - size_t len1 = strlen(str1), len2 = strlen(str2); - return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false; -} - -// Returns if string starts with another string -bool SystemTools::StringStartsWith(const std::string& str1, const char* str2) -{ - if (!str2) { - return false; - } - size_t len1 = str1.size(), len2 = strlen(str2); - return len1 >= len2 && !strncmp(str1.c_str(), str2, len2) ? true : false; -} - -// Returns if string ends with another string -bool SystemTools::StringEndsWith(const char* str1, const char* str2) -{ - if (!str1 || !str2) { - return false; - } - size_t len1 = strlen(str1), len2 = strlen(str2); - return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true - : false; -} - -// Returns if string ends with another string -bool SystemTools::StringEndsWith(const std::string& str1, const char* str2) -{ - if (!str2) { - return false; - } - size_t len1 = str1.size(), len2 = strlen(str2); - return len1 >= len2 && !strncmp(str1.c_str() + (len1 - len2), str2, len2) - ? true - : false; -} - -// Returns a pointer to the last occurrence of str2 in str1 -const char* SystemTools::FindLastString(const char* str1, const char* str2) -{ - if (!str1 || !str2) { - return nullptr; - } - - size_t len1 = strlen(str1), len2 = strlen(str2); - if (len1 >= len2) { - const char* ptr = str1 + len1 - len2; - do { - if (!strncmp(ptr, str2, len2)) { - return ptr; - } - } while (ptr-- != str1); - } - - return nullptr; -} - -// Duplicate string -char* SystemTools::DuplicateString(const char* str) -{ - if (str) { - char* newstr = new char[strlen(str) + 1]; - return strcpy(newstr, str); - } - return nullptr; -} - -// Return a cropped string -std::string SystemTools::CropString(const std::string& s, size_t max_len) -{ - if (!s.size() || max_len == 0 || max_len >= s.size()) { - return s; - } - - std::string n; - n.reserve(max_len); - - size_t middle = max_len / 2; - - n += s.substr(0, middle); - n += s.substr(s.size() - (max_len - middle)); - - if (max_len > 2) { - n[middle] = '.'; - if (max_len > 3) { - n[middle - 1] = '.'; - if (max_len > 4) { - n[middle + 1] = '.'; - } - } - } - - return n; -} - -std::vector<std::string> SystemTools::SplitString(const std::string& p, - char sep, bool isPath) -{ - std::string path = p; - std::vector<std::string> paths; - if (path.empty()) { - return paths; - } - if (isPath && path[0] == '/') { - path.erase(path.begin()); - paths.push_back("/"); - } - std::string::size_type pos1 = 0; - std::string::size_type pos2 = path.find(sep, pos1 + 1); - while (pos2 != std::string::npos) { - paths.push_back(path.substr(pos1, pos2 - pos1)); - pos1 = pos2 + 1; - pos2 = path.find(sep, pos1 + 1); - } - paths.push_back(path.substr(pos1, pos2 - pos1)); - - return paths; -} - -int SystemTools::EstimateFormatLength(const char* format, va_list ap) -{ - if (!format) { - return 0; - } - - // Quick-hack attempt at estimating the length of the string. - // Should never under-estimate. - - // Start with the length of the format string itself. - - size_t length = strlen(format); - - // Increase the length for every argument in the format. - - const char* cur = format; - while (*cur) { - if (*cur++ == '%') { - // Skip "%%" since it doesn't correspond to a va_arg. - if (*cur != '%') { - while (!int(isalpha(*cur))) { - ++cur; - } - switch (*cur) { - case 's': { - // Check the length of the string. - char* s = va_arg(ap, char*); - if (s) { - length += strlen(s); - } - } break; - case 'e': - case 'f': - case 'g': { - // Assume the argument contributes no more than 64 characters. - length += 64; - - // Eat the argument. - static_cast<void>(va_arg(ap, double)); - } break; - default: { - // Assume the argument contributes no more than 64 characters. - length += 64; - - // Eat the argument. - static_cast<void>(va_arg(ap, int)); - } break; - } - } - - // Move past the characters just tested. - ++cur; - } - } - - return static_cast<int>(length); -} - -std::string SystemTools::EscapeChars(const char* str, - const char* chars_to_escape, - char escape_char) -{ - std::string n; - if (str) { - if (!chars_to_escape || !*chars_to_escape) { - n.append(str); - } else { - n.reserve(strlen(str)); - while (*str) { - const char* ptr = chars_to_escape; - while (*ptr) { - if (*str == *ptr) { - n += escape_char; - break; - } - ++ptr; - } - n += *str; - ++str; - } - } - } - return n; -} - -#ifdef __VMS -static void ConvertVMSToUnix(std::string& path) -{ - std::string::size_type rootEnd = path.find(":["); - std::string::size_type pathEnd = path.find("]"); - if (rootEnd != std::string::npos) { - std::string root = path.substr(0, rootEnd); - std::string pathPart = path.substr(rootEnd + 2, pathEnd - rootEnd - 2); - const char* pathCString = pathPart.c_str(); - const char* pos0 = pathCString; - for (std::string::size_type pos = 0; *pos0; ++pos) { - if (*pos0 == '.') { - pathPart[pos] = '/'; - } - pos0++; - } - path = "/" + root + "/" + pathPart; - } -} -#endif - -// convert windows slashes to unix slashes -void SystemTools::ConvertToUnixSlashes(std::string& path) -{ - if (path.empty()) { - return; - } - - const char* pathCString = path.c_str(); - bool hasDoubleSlash = false; -#ifdef __VMS - ConvertVMSToUnix(path); -#else - const char* pos0 = pathCString; - for (std::string::size_type pos = 0; *pos0; ++pos) { - if (*pos0 == '\\') { - path[pos] = '/'; - } - - // Also, reuse the loop to check for slash followed by another slash - if (!hasDoubleSlash && *(pos0 + 1) == '/' && *(pos0 + 2) == '/') { -# ifdef _WIN32 - // However, on windows if the first characters are both slashes, - // then keep them that way, so that network paths can be handled. - if (pos > 0) { - hasDoubleSlash = true; - } -# else - hasDoubleSlash = true; -# endif - } - - pos0++; - } - - if (hasDoubleSlash) { - SystemTools::ReplaceString(path, "//", "/"); - } -#endif - - // remove any trailing slash - // if there is a tilda ~ then replace it with HOME - pathCString = path.c_str(); - if (pathCString[0] == '~' && - (pathCString[1] == '/' || pathCString[1] == '\0')) { - std::string homeEnv; - if (SystemTools::GetEnv("HOME", homeEnv)) { - path.replace(0, 1, homeEnv); - } - } -#ifdef HAVE_GETPWNAM - else if (pathCString[0] == '~') { - std::string::size_type idx = path.find_first_of("/\0"); - std::string user = path.substr(1, idx - 1); - passwd* pw = getpwnam(user.c_str()); - if (pw) { - path.replace(0, idx, pw->pw_dir); - } - } -#endif - // remove trailing slash if the path is more than - // a single / - pathCString = path.c_str(); - size_t size = path.size(); - if (size > 1 && path.back() == '/') { - // if it is c:/ then do not remove the trailing slash - if (!((size == 3 && pathCString[1] == ':'))) { - path.resize(size - 1); - } - } -} - -#ifdef _WIN32 -std::wstring SystemTools::ConvertToWindowsExtendedPath( - const std::string& source) -{ - return Encoding::ToWindowsExtendedPath(source); -} -#endif - -// change // to /, and escape any spaces in the path -std::string SystemTools::ConvertToUnixOutputPath(const std::string& path) -{ - std::string ret = path; - - // remove // except at the beginning might be a cygwin drive - std::string::size_type pos = 1; - while ((pos = ret.find("//", pos)) != std::string::npos) { - ret.erase(pos, 1); - } - // escape spaces and () in the path - if (ret.find_first_of(" ") != std::string::npos) { - std::string result; - char lastch = 1; - for (const char* ch = ret.c_str(); *ch != '\0'; ++ch) { - // if it is already escaped then don't try to escape it again - if ((*ch == ' ') && lastch != '\\') { - result += '\\'; - } - result += *ch; - lastch = *ch; - } - ret = result; - } - return ret; -} - -std::string SystemTools::ConvertToOutputPath(const std::string& path) -{ -#if defined(_WIN32) && !defined(__CYGWIN__) - return SystemTools::ConvertToWindowsOutputPath(path); -#else - return SystemTools::ConvertToUnixOutputPath(path); -#endif -} - -// remove double slashes not at the start -std::string SystemTools::ConvertToWindowsOutputPath(const std::string& path) -{ - std::string ret; - // make it big enough for all of path and double quotes - ret.reserve(path.size() + 3); - // put path into the string - ret = path; - std::string::size_type pos = 0; - // first convert all of the slashes - while ((pos = ret.find('/', pos)) != std::string::npos) { - ret[pos] = '\\'; - pos++; - } - // check for really small paths - if (ret.size() < 2) { - return ret; - } - // now clean up a bit and remove double slashes - // Only if it is not the first position in the path which is a network - // path on windows - pos = 1; // start at position 1 - if (ret[0] == '\"') { - pos = 2; // if the string is already quoted then start at 2 - if (ret.size() < 3) { - return ret; - } - } - while ((pos = ret.find("\\\\", pos)) != std::string::npos) { - ret.erase(pos, 1); - } - // now double quote the path if it has spaces in it - // and is not already double quoted - if (ret.find(' ') != std::string::npos && ret[0] != '\"') { - ret.insert(static_cast<std::string::size_type>(0), - static_cast<std::string::size_type>(1), '\"'); - ret.append(1, '\"'); - } - return ret; -} - -/** - * Append the filename from the path source to the directory name dir. - */ -static std::string FileInDir(const std::string& source, const std::string& dir) -{ - std::string new_destination = dir; - SystemTools::ConvertToUnixSlashes(new_destination); - return new_destination + '/' + SystemTools::GetFilenameName(source); -} - -bool SystemTools::CopyFileIfDifferent(const std::string& source, - const std::string& destination) -{ - // special check for a destination that is a directory - // FilesDiffer does not handle file to directory compare - if (SystemTools::FileIsDirectory(destination)) { - const std::string new_destination = FileInDir(source, destination); - return SystemTools::CopyFileIfDifferent(source, new_destination); - } - // source and destination are files so do a copy if they - // are different - if (SystemTools::FilesDiffer(source, destination)) { - return SystemTools::CopyFileAlways(source, destination); - } - // at this point the files must be the same so return true - return true; -} - -#define KWSYS_ST_BUFFER 4096 - -bool SystemTools::FilesDiffer(const std::string& source, - const std::string& destination) -{ - -#if defined(_WIN32) - WIN32_FILE_ATTRIBUTE_DATA statSource; - if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(source).c_str(), - GetFileExInfoStandard, &statSource) == 0) { - return true; - } - - WIN32_FILE_ATTRIBUTE_DATA statDestination; - if (GetFileAttributesExW( - Encoding::ToWindowsExtendedPath(destination).c_str(), - GetFileExInfoStandard, &statDestination) == 0) { - return true; - } - - if (statSource.nFileSizeHigh != statDestination.nFileSizeHigh || - statSource.nFileSizeLow != statDestination.nFileSizeLow) { - return true; - } - - if (statSource.nFileSizeHigh == 0 && statSource.nFileSizeLow == 0) { - return false; - } - off_t nleft = - ((__int64)statSource.nFileSizeHigh << 32) + statSource.nFileSizeLow; - -#else - - struct stat statSource; - if (stat(source.c_str(), &statSource) != 0) { - return true; - } - - struct stat statDestination; - if (stat(destination.c_str(), &statDestination) != 0) { - return true; - } - - if (statSource.st_size != statDestination.st_size) { - return true; - } - - if (statSource.st_size == 0) { - return false; - } - off_t nleft = statSource.st_size; -#endif - -#if defined(_WIN32) - kwsys::ifstream finSource(source.c_str(), (std::ios::binary | std::ios::in)); - kwsys::ifstream finDestination(destination.c_str(), - (std::ios::binary | std::ios::in)); -#else - kwsys::ifstream finSource(source.c_str()); - kwsys::ifstream finDestination(destination.c_str()); -#endif - if (!finSource || !finDestination) { - return true; - } - - // Compare the files a block at a time. - char source_buf[KWSYS_ST_BUFFER]; - char dest_buf[KWSYS_ST_BUFFER]; - while (nleft > 0) { - // Read a block from each file. - std::streamsize nnext = (nleft > KWSYS_ST_BUFFER) - ? KWSYS_ST_BUFFER - : static_cast<std::streamsize>(nleft); - finSource.read(source_buf, nnext); - finDestination.read(dest_buf, nnext); - - // If either failed to read assume they are different. - if (static_cast<std::streamsize>(finSource.gcount()) != nnext || - static_cast<std::streamsize>(finDestination.gcount()) != nnext) { - return true; - } - - // If this block differs the file differs. - if (memcmp(static_cast<const void*>(source_buf), - static_cast<const void*>(dest_buf), - static_cast<size_t>(nnext)) != 0) { - return true; - } - - // Update the byte count remaining. - nleft -= nnext; - } - - // No differences found. - return false; -} - -bool SystemTools::TextFilesDiffer(const std::string& path1, - const std::string& path2) -{ - kwsys::ifstream if1(path1.c_str()); - kwsys::ifstream if2(path2.c_str()); - if (!if1 || !if2) { - return true; - } - - for (;;) { - std::string line1, line2; - bool hasData1 = GetLineFromStream(if1, line1); - bool hasData2 = GetLineFromStream(if2, line2); - if (hasData1 != hasData2) { - return true; - } - if (!hasData1) { - break; - } - if (line1 != line2) { - return true; - } - } - return false; -} - -/** - * Blockwise copy source to destination file - */ -static bool CopyFileContentBlockwise(const std::string& source, - const std::string& destination) -{ -// Open files -#if defined(_WIN32) - kwsys::ifstream fin( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(), - std::ios::in | std::ios::binary); -#else - kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); -#endif - if (!fin) { - return false; - } - - // try and remove the destination file so that read only destination files - // can be written to. - // If the remove fails continue so that files in read only directories - // that do not allow file removal can be modified. - SystemTools::RemoveFile(destination); - -#if defined(_WIN32) - kwsys::ofstream fout( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(destination)).c_str(), - std::ios::out | std::ios::trunc | std::ios::binary); -#else - kwsys::ofstream fout(destination.c_str(), - std::ios::out | std::ios::trunc | std::ios::binary); -#endif - if (!fout) { - return false; - } - - // This copy loop is very sensitive on certain platforms with - // slightly broken stream libraries (like HPUX). Normally, it is - // incorrect to not check the error condition on the fin.read() - // before using the data, but the fin.gcount() will be zero if an - // error occurred. Therefore, the loop should be safe everywhere. - while (fin) { - const int bufferSize = 4096; - char buffer[bufferSize]; - - fin.read(buffer, bufferSize); - if (fin.gcount()) { - fout.write(buffer, fin.gcount()); - } else { - break; - } - } - - // Make sure the operating system has finished writing the file - // before closing it. This will ensure the file is finished before - // the check below. - fout.flush(); - - fin.close(); - fout.close(); - - if (!fout) { - return false; - } - - return true; -} - -/** - * Clone the source file to the destination file - * - * If available, the Linux FICLONE ioctl is used to create a check - * copy-on-write clone of the source file. - * - * The method returns false for the following cases: - * - The code has not been compiled on Linux or the ioctl was unknown - * - The source and destination is on different file systems - * - The underlying filesystem does not support file cloning - * - An unspecified error occurred - */ -static bool CloneFileContent(const std::string& source, - const std::string& destination) -{ -#if defined(__linux) && defined(FICLONE) - int in = open(source.c_str(), O_RDONLY); - if (in < 0) { - return false; - } - - SystemTools::RemoveFile(destination); - - int out = - open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); - if (out < 0) { - close(in); - return false; - } - - int result = ioctl(out, FICLONE, in); - close(in); - close(out); - - if (result < 0) { - return false; - } - - return true; -#else - (void)source; - (void)destination; - return false; -#endif -} - -/** - * Copy a file named by "source" to the file named by "destination". - */ -bool SystemTools::CopyFileAlways(const std::string& source, - const std::string& destination) -{ - mode_t perm = 0; - bool perms = SystemTools::GetPermissions(source, perm); - std::string real_destination = destination; - - if (SystemTools::FileIsDirectory(source)) { - SystemTools::MakeDirectory(destination); - } else { - // If destination is a directory, try to create a file with the same - // name as the source in that directory. - - std::string destination_dir; - if (SystemTools::FileIsDirectory(destination)) { - destination_dir = real_destination; - SystemTools::ConvertToUnixSlashes(real_destination); - real_destination += '/'; - std::string source_name = source; - real_destination += SystemTools::GetFilenameName(source_name); - } else { - destination_dir = SystemTools::GetFilenamePath(destination); - } - // If files are the same do not copy - if (SystemTools::SameFile(source, real_destination)) { - return true; - } - - // 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 (perms) { - if (!SystemTools::SetPermissions(real_destination, perm)) { - return false; - } - } - return true; -} - -bool SystemTools::CopyAFile(const std::string& source, - const std::string& destination, bool always) -{ - if (always) { - return SystemTools::CopyFileAlways(source, destination); - } else { - return SystemTools::CopyFileIfDifferent(source, destination); - } -} - -/** - * 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) -{ - Directory dir; - if (dir.Load(source) == 0) { - return false; - } - size_t fileNum; - if (!SystemTools::MakeDirectory(destination)) { - return false; - } - for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { - if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") && - strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..")) { - std::string fullPath = source; - fullPath += "/"; - fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); - if (SystemTools::FileIsDirectory(fullPath)) { - std::string fullDestPath = destination; - fullDestPath += "/"; - fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum)); - if (!SystemTools::CopyADirectory(fullPath, fullDestPath, always)) { - return false; - } - } else { - if (!SystemTools::CopyAFile(fullPath, destination, always)) { - return false; - } - } - } - } - - return true; -} - -// return size of file; also returns zero if no file exists -unsigned long SystemTools::FileLength(const std::string& filename) -{ - unsigned long length = 0; -#ifdef _WIN32 - WIN32_FILE_ATTRIBUTE_DATA fs; - if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(), - GetFileExInfoStandard, &fs) != 0) { - /* To support the full 64-bit file size, use fs.nFileSizeHigh - * and fs.nFileSizeLow to construct the 64 bit size - - length = ((__int64)fs.nFileSizeHigh << 32) + fs.nFileSizeLow; - */ - length = static_cast<unsigned long>(fs.nFileSizeLow); - } -#else - struct stat fs; - if (stat(filename.c_str(), &fs) == 0) { - length = static_cast<unsigned long>(fs.st_size); - } -#endif - return length; -} - -int SystemTools::Strucmp(const char* l, const char* r) -{ - int lc; - int rc; - do { - lc = tolower(*l++); - rc = tolower(*r++); - } while (lc == rc && lc); - return lc - rc; -} - -// return file's modified time -long int SystemTools::ModifiedTime(const std::string& filename) -{ - long int mt = 0; -#ifdef _WIN32 - WIN32_FILE_ATTRIBUTE_DATA fs; - if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(), - GetFileExInfoStandard, &fs) != 0) { - mt = windows_filetime_to_posix_time(fs.ftLastWriteTime); - } -#else - struct stat fs; - if (stat(filename.c_str(), &fs) == 0) { - mt = static_cast<long int>(fs.st_mtime); - } -#endif - return mt; -} - -// return file's creation time -long int SystemTools::CreationTime(const std::string& filename) -{ - long int ct = 0; -#ifdef _WIN32 - WIN32_FILE_ATTRIBUTE_DATA fs; - if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(), - GetFileExInfoStandard, &fs) != 0) { - ct = windows_filetime_to_posix_time(fs.ftCreationTime); - } -#else - struct stat fs; - if (stat(filename.c_str(), &fs) == 0) { - ct = fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0; - } -#endif - return ct; -} - -std::string SystemTools::GetLastSystemError() -{ - int e = errno; - return strerror(e); -} - -bool SystemTools::RemoveFile(const std::string& source) -{ -#ifdef _WIN32 - std::wstring const& ws = Encoding::ToWindowsExtendedPath(source); - if (DeleteFileW(ws.c_str())) { - return true; - } - DWORD err = GetLastError(); - if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) { - return true; - } - if (err != ERROR_ACCESS_DENIED) { - return false; - } - /* 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; - } - - const DWORD DIRECTORY_SOFT_LINK_ATTRS = - FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT; - DWORD attrs = GetFileAttributesW(ws.c_str()); - if (attrs != INVALID_FILE_ATTRIBUTES && - (attrs & DIRECTORY_SOFT_LINK_ATTRS) == DIRECTORY_SOFT_LINK_ATTRS && - RemoveDirectoryW(ws.c_str())) { - return true; - } - if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND || - GetLastError() == ERROR_PATH_NOT_FOUND) { - return true; - } - /* Try to restore the original permissions. */ - SystemTools::SetPermissions(source, mode); - SetLastError(err); - return false; -#else - return unlink(source.c_str()) == 0 || errno == ENOENT; -#endif -} - -bool SystemTools::RemoveADirectory(const std::string& source) -{ - // Add write permission to the directory so we can modify its - // content to remove files and directories from it. - mode_t mode; - if (SystemTools::GetPermissions(source, mode)) { -#if defined(_WIN32) && !defined(__CYGWIN__) - mode |= S_IWRITE; -#else - mode |= S_IWUSR; -#endif - SystemTools::SetPermissions(source, mode); - } - - Directory dir; - dir.Load(source); - size_t fileNum; - for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { - if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") && - strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..")) { - std::string fullPath = source; - fullPath += "/"; - fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); - if (SystemTools::FileIsDirectory(fullPath) && - !SystemTools::FileIsSymlink(fullPath)) { - if (!SystemTools::RemoveADirectory(fullPath)) { - return false; - } - } else { - if (!SystemTools::RemoveFile(fullPath)) { - return false; - } - } - } - } - - return (Rmdir(source) == 0); -} - -/** - */ -size_t SystemTools::GetMaximumFilePathLength() -{ - return KWSYS_SYSTEMTOOLS_MAXPATH; -} - -/** - * Find the file the given name. Searches the given path and then - * the system search path. Returns the full path to the file if it is - * found. Otherwise, the empty string is returned. - */ -std::string SystemToolsStatic::FindName( - const std::string& name, const std::vector<std::string>& userPaths, - bool no_system_path) -{ - // Add the system search path to our path first - std::vector<std::string> path; - if (!no_system_path) { - SystemTools::GetPath(path, "CMAKE_FILE_PATH"); - SystemTools::GetPath(path); - } - // now add the additional paths - path.reserve(path.size() + userPaths.size()); - path.insert(path.end(), userPaths.begin(), userPaths.end()); - // now look for the file - std::string tryPath; - for (std::string const& p : path) { - tryPath = p; - if (tryPath.empty() || tryPath.back() != '/') { - tryPath += '/'; - } - tryPath += name; - if (SystemTools::FileExists(tryPath)) { - return tryPath; - } - } - // Couldn't find the file. - return ""; -} - -/** - * Find the file the given name. Searches the given path and then - * the system search path. Returns the full path to the file if it is - * found. Otherwise, the empty string is returned. - */ -std::string SystemTools::FindFile(const std::string& name, - const std::vector<std::string>& userPaths, - bool no_system_path) -{ - std::string tryPath = - SystemToolsStatic::FindName(name, userPaths, no_system_path); - if (!tryPath.empty() && !SystemTools::FileIsDirectory(tryPath)) { - return SystemTools::CollapseFullPath(tryPath); - } - // Couldn't find the file. - return ""; -} - -/** - * Find the directory the given name. Searches the given path and then - * the system search path. Returns the full path to the directory if it is - * found. Otherwise, the empty string is returned. - */ -std::string SystemTools::FindDirectory( - const std::string& name, const std::vector<std::string>& userPaths, - bool no_system_path) -{ - std::string tryPath = - SystemToolsStatic::FindName(name, userPaths, no_system_path); - if (!tryPath.empty() && SystemTools::FileIsDirectory(tryPath)) { - return SystemTools::CollapseFullPath(tryPath); - } - // Couldn't find the file. - return ""; -} - -/** - * Find the executable with the given name. Searches the given path and then - * the system search path. Returns the full path to the executable if it is - * found. Otherwise, the empty string is returned. - */ -std::string SystemTools::FindProgram(const char* nameIn, - const std::vector<std::string>& userPaths, - bool no_system_path) -{ - if (!nameIn || !*nameIn) { - return ""; - } - return SystemTools::FindProgram(std::string(nameIn), userPaths, - no_system_path); -} - -std::string SystemTools::FindProgram(const std::string& name, - const std::vector<std::string>& userPaths, - bool no_system_path) -{ - std::string tryPath; - -#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) - std::vector<std::string> extensions; - // check to see if the name already has a .xxx at - // the end of it - // on windows try .com then .exe - if (name.size() <= 3 || name[name.size() - 4] != '.') { - extensions.emplace_back(".com"); - extensions.emplace_back(".exe"); - - // first try with extensions if the os supports them - for (std::string const& ext : extensions) { - tryPath = name; - tryPath += ext; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } - } - } -#endif - - // now try just the name - if (SystemTools::FileExists(name, true)) { - return SystemTools::CollapseFullPath(name); - } - // now construct the path - std::vector<std::string> path; - // Add the system search path to our path. - if (!no_system_path) { - SystemTools::GetPath(path); - } - // now add the additional paths - path.reserve(path.size() + userPaths.size()); - path.insert(path.end(), userPaths.begin(), userPaths.end()); - // Add a trailing slash to all paths to aid the search process. - for (std::string& p : path) { - if (p.empty() || p.back() != '/') { - p += '/'; - } - } - // Try each path - for (std::string& p : path) { -#ifdef _WIN32 - // Remove double quotes from the path on windows - SystemTools::ReplaceString(p, "\"", ""); -#endif -#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) - // first try with extensions - for (std::string const& ext : extensions) { - tryPath = p; - tryPath += name; - tryPath += ext; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } - } -#endif - // now try it without them - tryPath = p; - tryPath += name; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } - } - // Couldn't find the program. - return ""; -} - -std::string SystemTools::FindProgram(const std::vector<std::string>& names, - const std::vector<std::string>& path, - bool noSystemPath) -{ - for (std::string const& name : names) { - // Try to find the program. - std::string result = SystemTools::FindProgram(name, path, noSystemPath); - if (!result.empty()) { - return result; - } - } - return ""; -} - -/** - * Find the library with the given name. Searches the given path and then - * the system search path. Returns the full path to the library if it is - * found. Otherwise, the empty string is returned. - */ -std::string SystemTools::FindLibrary(const std::string& name, - const std::vector<std::string>& userPaths) -{ - // See if the executable exists as written. - if (SystemTools::FileExists(name, true)) { - return SystemTools::CollapseFullPath(name); - } - - // Add the system search path to our path. - std::vector<std::string> path; - SystemTools::GetPath(path); - // now add the additional paths - path.reserve(path.size() + userPaths.size()); - path.insert(path.end(), userPaths.begin(), userPaths.end()); - // Add a trailing slash to all paths to aid the search process. - for (std::string& p : path) { - if (p.empty() || p.back() != '/') { - p += '/'; - } - } - std::string tryPath; - for (std::string const& p : path) { -#if defined(__APPLE__) - tryPath = p; - tryPath += name; - tryPath += ".framework"; - if (SystemTools::FileIsDirectory(tryPath)) { - return SystemTools::CollapseFullPath(tryPath); - } -#endif -#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) - tryPath = p; - tryPath += name; - tryPath += ".lib"; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } -#else - tryPath = p; - tryPath += "lib"; - tryPath += name; - tryPath += ".so"; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } - tryPath = p; - tryPath += "lib"; - tryPath += name; - tryPath += ".a"; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } - tryPath = p; - tryPath += "lib"; - tryPath += name; - tryPath += ".sl"; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } - tryPath = p; - tryPath += "lib"; - tryPath += name; - tryPath += ".dylib"; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } - tryPath = p; - tryPath += "lib"; - tryPath += name; - tryPath += ".dll"; - if (SystemTools::FileExists(tryPath, true)) { - return SystemTools::CollapseFullPath(tryPath); - } -#endif - } - - // Couldn't find the library. - return ""; -} - -std::string SystemTools::GetRealPath(const std::string& path, - std::string* errorMessage) -{ - std::string ret; - Realpath(path, ret, errorMessage); - return ret; -} - -bool SystemTools::FileIsDirectory(const std::string& inName) -{ - if (inName.empty()) { - return false; - } - size_t length = inName.size(); - const char* name = inName.c_str(); - - // Remove any trailing slash from the name except in a root component. - char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; - std::string string_buffer; - size_t last = length - 1; - if (last > 0 && (name[last] == '/' || name[last] == '\\') && - strcmp(name, "/") != 0 && name[last - 1] != ':') { - if (last < sizeof(local_buffer)) { - memcpy(local_buffer, name, last); - local_buffer[last] = '\0'; - name = local_buffer; - } else { - string_buffer.append(name, last); - name = string_buffer.c_str(); - } - } - -// Now check the file node type. -#if defined(_WIN32) - DWORD attr = - GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str()); - if (attr != INVALID_FILE_ATTRIBUTES) { - return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; -#else - struct stat fs; - if (stat(name, &fs) == 0) { - return S_ISDIR(fs.st_mode); -#endif - } else { - return false; - } -} - -bool SystemTools::FileIsSymlink(const std::string& name) -{ -#if defined(_WIN32) - std::wstring path = Encoding::ToWindowsExtendedPath(name); - DWORD attr = GetFileAttributesW(path.c_str()); - if (attr != INVALID_FILE_ATTRIBUTES) { - if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { - // 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( - path.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 false; - } - byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - DWORD bytesReturned = 0; - if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, nullptr, 0, buffer, - MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, - nullptr)) { - CloseHandle(hFile); - // Since FILE_ATTRIBUTE_REPARSE_POINT is set this file must be - // a symbolic link if it is not a reparse point. - return GetLastError() == ERROR_NOT_A_REPARSE_POINT; - } - CloseHandle(hFile); - ULONG reparseTag = - reinterpret_cast<PREPARSE_GUID_DATA_BUFFER>(&buffer[0])->ReparseTag; - return (reparseTag == IO_REPARSE_TAG_SYMLINK) || - (reparseTag == IO_REPARSE_TAG_MOUNT_POINT); - } - return false; - } else { - return false; - } -#else - struct stat fs; - if (lstat(name.c_str(), &fs) == 0) { - return S_ISLNK(fs.st_mode); - } else { - return false; - } -#endif -} - -bool SystemTools::FileIsFIFO(const std::string& name) -{ -#if defined(_WIN32) - HANDLE hFile = - CreateFileW(Encoding::ToWide(name).c_str(), GENERIC_READ, FILE_SHARE_READ, - nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (hFile == INVALID_HANDLE_VALUE) { - return false; - } - const DWORD type = GetFileType(hFile); - CloseHandle(hFile); - return type == FILE_TYPE_PIPE; -#else - struct stat fs; - if (lstat(name.c_str(), &fs) == 0) { - return S_ISFIFO(fs.st_mode); - } else { - return false; - } -#endif -} - -#if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::CreateSymlink(const std::string&, const std::string&) -{ - return false; -} -#else -bool SystemTools::CreateSymlink(const std::string& origName, - const std::string& newName) -{ - return symlink(origName.c_str(), newName.c_str()) >= 0; -} -#endif - -#if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::ReadSymlink(const std::string&, std::string&) -{ - return false; -} -#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; - } -} -#endif - -int SystemTools::ChangeDirectory(const std::string& dir) -{ - return Chdir(dir); -} - -std::string SystemTools::GetCurrentWorkingDirectory(bool collapse) -{ - char buf[2048]; - const char* cwd = Getcwd(buf, 2048); - std::string path; - if (cwd) { - path = cwd; - } - if (collapse) { - return SystemTools::CollapseFullPath(path); - } - return path; -} - -std::string SystemTools::GetProgramPath(const std::string& in_name) -{ - std::string dir, file; - SystemTools::SplitProgramPath(in_name, dir, file); - return dir; -} - -bool SystemTools::SplitProgramPath(const std::string& in_name, - std::string& dir, std::string& file, bool) -{ - dir = in_name; - file = ""; - SystemTools::ConvertToUnixSlashes(dir); - - if (!SystemTools::FileIsDirectory(dir)) { - std::string::size_type slashPos = dir.rfind("/"); - if (slashPos != std::string::npos) { - file = dir.substr(slashPos + 1); - dir = dir.substr(0, slashPos); - } else { - file = dir; - dir = ""; - } - } - if (!(dir.empty()) && !SystemTools::FileIsDirectory(dir)) { - std::string oldDir = in_name; - SystemTools::ConvertToUnixSlashes(oldDir); - dir = in_name; - return false; - } - return true; -} - -bool SystemTools::FindProgramPath(const char* argv0, std::string& pathOut, - std::string& errorMsg, const char* exeName, - const char* buildDir, - const char* installPrefix) -{ - std::vector<std::string> failures; - std::string self = argv0 ? argv0 : ""; - failures.push_back(self); - SystemTools::ConvertToUnixSlashes(self); - self = SystemTools::FindProgram(self); - if (!SystemTools::FileExists(self)) { - if (buildDir) { - std::string intdir = "."; -#ifdef CMAKE_INTDIR - intdir = CMAKE_INTDIR; -#endif - self = buildDir; - self += "/bin/"; - self += intdir; - self += "/"; - self += exeName; - self += SystemTools::GetExecutableExtension(); - } - } - if (installPrefix) { - if (!SystemTools::FileExists(self)) { - failures.push_back(self); - self = installPrefix; - self += "/bin/"; - self += exeName; - } - } - if (!SystemTools::FileExists(self)) { - failures.push_back(self); - std::ostringstream msg; - msg << "Can not find the command line program "; - if (exeName) { - msg << exeName; - } - msg << "\n"; - if (argv0) { - msg << " argv[0] = \"" << argv0 << "\"\n"; - } - msg << " Attempted paths:\n"; - for (std::string const& ff : failures) { - msg << " \"" << ff << "\"\n"; - } - errorMsg = msg.str(); - return false; - } - pathOut = self; - return true; -} - -std::string SystemTools::CollapseFullPath(const std::string& in_relative) -{ - return SystemTools::CollapseFullPath(in_relative, nullptr); -} - -#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP -void SystemTools::AddTranslationPath(const std::string& a, - const std::string& b) -{ - std::string path_a = a; - std::string path_b = b; - SystemTools::ConvertToUnixSlashes(path_a); - SystemTools::ConvertToUnixSlashes(path_b); - // First check this is a directory path, since we don't want the table to - // grow too fat - if (SystemTools::FileIsDirectory(path_a)) { - // Make sure the path is a full path and does not contain no '..' - // Ken--the following code is incorrect. .. can be in a valid path - // for example /home/martink/MyHubba...Hubba/Src - if (SystemTools::FileIsFullPath(path_b) && - path_b.find("..") == std::string::npos) { - // Before inserting make sure path ends with '/' - if (!path_a.empty() && path_a.back() != '/') { - path_a += '/'; - } - if (!path_b.empty() && path_b.back() != '/') { - path_b += '/'; - } - if (!(path_a == path_b)) { - SystemTools::Statics->TranslationMap.insert( - SystemToolsStatic::StringMap::value_type(std::move(path_a), - std::move(path_b))); - } - } - } -} - -void SystemTools::AddKeepPath(const std::string& dir) -{ - std::string cdir; - Realpath(SystemTools::CollapseFullPath(dir), cdir); - SystemTools::AddTranslationPath(cdir, dir); -} - -void SystemTools::CheckTranslationPath(std::string& path) -{ - // Do not translate paths that are too short to have meaningful - // translations. - if (path.size() < 2) { - return; - } - - // Always add a trailing slash before translation. It does not - // matter if this adds an extra slash, but we do not want to - // translate part of a directory (like the foo part of foo-dir). - path += '/'; - - // In case a file was specified we still have to go through this: - // Now convert any path found in the table back to the one desired: - for (auto const& pair : SystemTools::Statics->TranslationMap) { - // We need to check of the path is a substring of the other path - if (path.find(pair.first) == 0) { - path = path.replace(0, pair.first.size(), pair.second); - } - } - - // Remove the trailing slash we added before. - path.pop_back(); -} -#endif - -static void SystemToolsAppendComponents( - std::vector<std::string>& out_components, - std::vector<std::string>::iterator first, - std::vector<std::string>::iterator last) -{ - static const std::string up = ".."; - static const std::string cur = "."; - for (std::vector<std::string>::const_iterator i = first; i != last; ++i) { - if (*i == up) { - // Remove the previous component if possible. Ignore ../ components - // that try to go above the root. Keep ../ components if they are - // at the beginning of a relative path (base path is relative). - if (out_components.size() > 1 && out_components.back() != up) { - out_components.resize(out_components.size() - 1); - } else if (!out_components.empty() && out_components[0].empty()) { - out_components.emplace_back(std::move(*i)); - } - } else if (!i->empty() && *i != cur) { - out_components.emplace_back(std::move(*i)); - } - } -} - -std::string SystemTools::CollapseFullPath(const std::string& in_path, - const char* in_base) -{ - // Use the current working directory as a base path. - char buf[2048]; - const char* res_in_base = in_base; - if (!res_in_base) { - if (const char* cwd = Getcwd(buf, 2048)) { - res_in_base = cwd; - } else { - res_in_base = ""; - } - } - - return SystemTools::CollapseFullPath(in_path, std::string(res_in_base)); -} - -std::string SystemTools::CollapseFullPath(const std::string& in_path, - const std::string& in_base) -{ - // Collect the output path components. - std::vector<std::string> out_components; - - // Split the input path components. - std::vector<std::string> path_components; - SystemTools::SplitPath(in_path, path_components); - out_components.reserve(path_components.size()); - - // If the input path is relative, start with a base path. - if (path_components[0].empty()) { - std::vector<std::string> base_components; - // Use the given base path. - SystemTools::SplitPath(in_base, base_components); - - // Append base path components to the output path. - out_components.push_back(base_components[0]); - SystemToolsAppendComponents(out_components, base_components.begin() + 1, - base_components.end()); - } - - // Append input path components to the output path. - SystemToolsAppendComponents(out_components, path_components.begin(), - path_components.end()); - - // Transform the path back to a string. - std::string newPath = SystemTools::JoinPath(out_components); - -#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP - // Update the translation table with this potentially new path. I am not - // sure why this line is here, it seems really questionable, but yet I - // would put good money that if I remove it something will break, basically - // from what I can see it created a mapping from the collapsed path, to be - // replaced by the input path, which almost completely does the opposite of - // this function, the only thing preventing this from happening a lot is - // that if the in_path has a .. in it, then it is not added to the - // translation table. So for most calls this either does nothing due to the - // .. or it adds a translation between identical paths as nothing was - // collapsed, so I am going to try to comment it out, and see what hits the - // fan, hopefully quickly. - // Commented out line below: - // SystemTools::AddTranslationPath(newPath, in_path); - - SystemTools::CheckTranslationPath(newPath); -#endif -#ifdef _WIN32 - newPath = SystemTools::Statics->GetActualCaseForPathCached(newPath); - SystemTools::ConvertToUnixSlashes(newPath); -#endif - // Return the reconstructed path. - return newPath; -} - -// compute the relative path from here to there -std::string SystemTools::RelativePath(const std::string& local, - const std::string& remote) -{ - if (!SystemTools::FileIsFullPath(local)) { - return ""; - } - if (!SystemTools::FileIsFullPath(remote)) { - return ""; - } - - std::string l = SystemTools::CollapseFullPath(local); - std::string r = SystemTools::CollapseFullPath(remote); - - // split up both paths into arrays of strings using / as a separator - std::vector<std::string> localSplit = SystemTools::SplitString(l, '/', true); - std::vector<std::string> remoteSplit = - SystemTools::SplitString(r, '/', true); - std::vector<std::string> - commonPath; // store shared parts of path in this array - std::vector<std::string> finalPath; // store the final relative path here - // count up how many matching directory names there are from the start - unsigned int sameCount = 0; - while (((sameCount <= (localSplit.size() - 1)) && - (sameCount <= (remoteSplit.size() - 1))) && -// for Windows and Apple do a case insensitive string compare -#if defined(_WIN32) || defined(__APPLE__) - SystemTools::Strucmp(localSplit[sameCount].c_str(), - remoteSplit[sameCount].c_str()) == 0 -#else - localSplit[sameCount] == remoteSplit[sameCount] -#endif - ) { - // put the common parts of the path into the commonPath array - commonPath.push_back(localSplit[sameCount]); - // erase the common parts of the path from the original path arrays - localSplit[sameCount] = ""; - remoteSplit[sameCount] = ""; - sameCount++; - } - - // If there is nothing in common at all then just return the full - // path. This is the case only on windows when the paths have - // different drive letters. On unix two full paths always at least - // have the root "/" in common so we will return a relative path - // that passes through the root directory. - if (sameCount == 0) { - return remote; - } - - // for each entry that is not common in the local path - // add a ../ to the finalpath array, this gets us out of the local - // path into the remote dir - for (std::string const& lp : localSplit) { - if (!lp.empty()) { - finalPath.emplace_back("../"); - } - } - // for each entry that is not common in the remote path add it - // to the final path. - for (std::string const& rp : remoteSplit) { - if (!rp.empty()) { - finalPath.push_back(rp); - } - } - std::string relativePath; // result string - // now turn the array of directories into a unix path by puttint / - // between each entry that does not already have one - for (std::string const& fp : finalPath) { - if (!relativePath.empty() && relativePath.back() != '/') { - relativePath += '/'; - } - relativePath += fp; - } - return relativePath; -} - -std::string SystemTools::GetActualCaseForPath(const std::string& p) -{ -#ifdef _WIN32 - return SystemToolsStatic::GetCasePathName(p); -#else - return p; -#endif -} - -const char* SystemTools::SplitPathRootComponent(const std::string& p, - std::string* root) -{ - // Identify the root component. - const char* c = p.c_str(); - if ((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\')) { - // Network path. - if (root) { - *root = "//"; - } - c += 2; - } else if (c[0] == '/' || c[0] == '\\') { - // Unix path (or Windows path w/out drive letter). - if (root) { - *root = "/"; - } - c += 1; - } else if (c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\')) { - // Windows path. - if (root) { - (*root) = "_:/"; - (*root)[0] = c[0]; - } - c += 3; - } else if (c[0] && c[1] == ':') { - // Path relative to a windows drive working directory. - if (root) { - (*root) = "_:"; - (*root)[0] = c[0]; - } - c += 2; - } else if (c[0] == '~') { - // Home directory. The returned root should always have a - // trailing slash so that appending components as - // c[0]c[1]/c[2]/... works. The remaining path returned should - // skip the first slash if it exists: - // - // "~" : root = "~/" , return "" - // "~/ : root = "~/" , return "" - // "~/x : root = "~/" , return "x" - // "~u" : root = "~u/", return "" - // "~u/" : root = "~u/", return "" - // "~u/x" : root = "~u/", return "x" - size_t n = 1; - while (c[n] && c[n] != '/') { - ++n; - } - if (root) { - root->assign(c, n); - *root += '/'; - } - if (c[n] == '/') { - ++n; - } - c += n; - } else { - // Relative path. - if (root) { - *root = ""; - } - } - - // Return the remaining path. - return c; -} - -void SystemTools::SplitPath(const std::string& p, - std::vector<std::string>& components, - bool expand_home_dir) -{ - const char* c; - components.clear(); - - // Identify the root component. - { - std::string root; - c = SystemTools::SplitPathRootComponent(p, &root); - - // Expand home directory references if requested. - if (expand_home_dir && !root.empty() && root[0] == '~') { - std::string homedir; - root = root.substr(0, root.size() - 1); - if (root.size() == 1) { -#if defined(_WIN32) && !defined(__CYGWIN__) - if (!SystemTools::GetEnv("USERPROFILE", homedir)) -#endif - SystemTools::GetEnv("HOME", homedir); - } -#ifdef HAVE_GETPWNAM - else if (passwd* pw = getpwnam(root.c_str() + 1)) { - if (pw->pw_dir) { - homedir = pw->pw_dir; - } - } -#endif - if (!homedir.empty() && - (homedir.back() == '/' || homedir.back() == '\\')) { - homedir.resize(homedir.size() - 1); - } - SystemTools::SplitPath(homedir, components); - } else { - components.push_back(root); - } - } - - // Parse the remaining components. - const char* first = c; - const char* last = first; - for (; *last; ++last) { - if (*last == '/' || *last == '\\') { - // End of a component. Save it. - components.push_back(std::string(first, last)); - first = last + 1; - } - } - - // Save the last component unless there were no components. - if (last != c) { - components.push_back(std::string(first, last)); - } -} - -std::string SystemTools::JoinPath(const std::vector<std::string>& components) -{ - return SystemTools::JoinPath(components.begin(), components.end()); -} - -std::string SystemTools::JoinPath( - std::vector<std::string>::const_iterator first, - std::vector<std::string>::const_iterator last) -{ - // Construct result in a single string. - std::string result; - size_t len = 0; - for (std::vector<std::string>::const_iterator i = first; i != last; ++i) { - len += 1 + i->size(); - } - result.reserve(len); - - // The first two components do not add a slash. - if (first != last) { - result.append(*first++); - } - if (first != last) { - result.append(*first++); - } - - // All remaining components are always separated with a slash. - while (first != last) { - result.push_back('/'); - result.append((*first++)); - } - - // Return the concatenated result. - return result; -} - -bool SystemTools::ComparePath(const std::string& c1, const std::string& c2) -{ -#if defined(_WIN32) || defined(__APPLE__) -# ifdef _MSC_VER - return _stricmp(c1.c_str(), c2.c_str()) == 0; -# elif defined(__APPLE__) || defined(__GNUC__) - return strcasecmp(c1.c_str(), c2.c_str()) == 0; -# else - return SystemTools::Strucmp(c1.c_str(), c2.c_str()) == 0; -# endif -#else - return c1 == c2; -#endif -} - -bool SystemTools::Split(const std::string& str, - std::vector<std::string>& lines, char separator) -{ - std::string data(str); - std::string::size_type lpos = 0; - while (lpos < data.length()) { - std::string::size_type rpos = data.find_first_of(separator, lpos); - if (rpos == std::string::npos) { - // String ends at end of string without a separator. - lines.push_back(data.substr(lpos)); - return false; - } else { - // String ends in a separator, remove the character. - lines.push_back(data.substr(lpos, rpos - lpos)); - } - lpos = rpos + 1; - } - return true; -} - -bool SystemTools::Split(const std::string& str, - std::vector<std::string>& lines) -{ - std::string data(str); - std::string::size_type lpos = 0; - while (lpos < data.length()) { - std::string::size_type rpos = data.find_first_of('\n', lpos); - if (rpos == std::string::npos) { - // Line ends at end of string without a newline. - lines.push_back(data.substr(lpos)); - return false; - } - if ((rpos > lpos) && (data[rpos - 1] == '\r')) { - // Line ends in a "\r\n" pair, remove both characters. - lines.push_back(data.substr(lpos, (rpos - 1) - lpos)); - } else { - // Line ends in a "\n", remove the character. - lines.push_back(data.substr(lpos, rpos - lpos)); - } - lpos = rpos + 1; - } - return true; -} - -/** - * Return path of a full filename (no trailing slashes). - * Warning: returned path is converted to Unix slashes format. - */ -std::string SystemTools::GetFilenamePath(const std::string& filename) -{ - std::string fn = filename; - SystemTools::ConvertToUnixSlashes(fn); - - std::string::size_type slash_pos = fn.rfind("/"); - if (slash_pos != std::string::npos) { - std::string ret = fn.substr(0, slash_pos); - if (ret.size() == 2 && ret[1] == ':') { - return ret + '/'; - } - if (ret.empty()) { - return "/"; - } - return ret; - } else { - return ""; - } -} - -/** - * Return file name of a full filename (i.e. file name without path). - */ -std::string SystemTools::GetFilenameName(const std::string& filename) -{ -#if defined(_WIN32) || defined(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES) - const char* separators = "/\\"; -#else - char separators = '/'; -#endif - std::string::size_type slash_pos = filename.find_last_of(separators); - if (slash_pos != std::string::npos) { - return filename.substr(slash_pos + 1); - } else { - return filename; - } -} - -/** - * Return file extension of a full filename (dot included). - * Warning: this is the longest extension (for example: .tar.gz) - */ -std::string SystemTools::GetFilenameExtension(const std::string& filename) -{ - std::string name = SystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.find('.'); - if (dot_pos != std::string::npos) { - return name.substr(dot_pos); - } else { - return ""; - } -} - -/** - * Return file extension of a full filename (dot included). - * Warning: this is the shortest extension (for example: .gz of .tar.gz) - */ -std::string SystemTools::GetFilenameLastExtension(const std::string& filename) -{ - std::string name = SystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.rfind('.'); - if (dot_pos != std::string::npos) { - return name.substr(dot_pos); - } else { - return ""; - } -} - -/** - * Return file name without extension of a full filename (i.e. without path). - * Warning: it considers the longest extension (for example: .tar.gz) - */ -std::string SystemTools::GetFilenameWithoutExtension( - const std::string& filename) -{ - std::string name = SystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.find('.'); - if (dot_pos != std::string::npos) { - return name.substr(0, dot_pos); - } else { - return name; - } -} - -/** - * Return file name without extension of a full filename (i.e. without path). - * Warning: it considers the last extension (for example: removes .gz - * from .tar.gz) - */ -std::string SystemTools::GetFilenameWithoutLastExtension( - const std::string& filename) -{ - std::string name = SystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.rfind('.'); - if (dot_pos != std::string::npos) { - return name.substr(0, dot_pos); - } else { - return name; - } -} - -bool SystemTools::FileHasSignature(const char* filename, const char* signature, - long offset) -{ - if (!filename || !signature) { - return false; - } - - FILE* fp = Fopen(filename, "rb"); - if (!fp) { - return false; - } - - fseek(fp, offset, SEEK_SET); - - bool res = false; - size_t signature_len = strlen(signature); - char* buffer = new char[signature_len]; - - if (fread(buffer, 1, signature_len, fp) == signature_len) { - res = (!strncmp(buffer, signature, signature_len) ? true : false); - } - - delete[] buffer; - - fclose(fp); - return res; -} - -SystemTools::FileTypeEnum SystemTools::DetectFileType(const char* filename, - unsigned long length, - double percent_bin) -{ - if (!filename || percent_bin < 0) { - return SystemTools::FileTypeUnknown; - } - - if (SystemTools::FileIsDirectory(filename)) { - return SystemTools::FileTypeUnknown; - } - - FILE* fp = Fopen(filename, "rb"); - if (!fp) { - return SystemTools::FileTypeUnknown; - } - - // Allocate buffer and read bytes - - unsigned char* buffer = new unsigned char[length]; - size_t read_length = fread(buffer, 1, length, fp); - fclose(fp); - if (read_length == 0) { - delete[] buffer; - return SystemTools::FileTypeUnknown; - } - - // Loop over contents and count - - size_t text_count = 0; - - const unsigned char* ptr = buffer; - const unsigned char* buffer_end = buffer + read_length; - - while (ptr != buffer_end) { - if ((*ptr >= 0x20 && *ptr <= 0x7F) || *ptr == '\n' || *ptr == '\r' || - *ptr == '\t') { - text_count++; - } - ptr++; - } - - delete[] buffer; - - double current_percent_bin = (static_cast<double>(read_length - text_count) / - static_cast<double>(read_length)); - - if (current_percent_bin >= percent_bin) { - return SystemTools::FileTypeBinary; - } - - return SystemTools::FileTypeText; -} - -bool SystemTools::LocateFileInDir(const char* filename, const char* dir, - std::string& filename_found, - int try_filename_dirs) -{ - if (!filename || !dir) { - return false; - } - - // Get the basename of 'filename' - - std::string filename_base = SystemTools::GetFilenameName(filename); - - // Check if 'dir' is really a directory - // If win32 and matches something like C:, accept it as a dir - - std::string real_dir; - if (!SystemTools::FileIsDirectory(dir)) { -#if defined(_WIN32) - size_t dir_len = strlen(dir); - if (dir_len < 2 || dir[dir_len - 1] != ':') { -#endif - real_dir = SystemTools::GetFilenamePath(dir); - dir = real_dir.c_str(); -#if defined(_WIN32) - } -#endif - } - - // Try to find the file in 'dir' - - bool res = false; - if (!filename_base.empty() && dir) { - size_t dir_len = strlen(dir); - int need_slash = - (dir_len && dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\'); - - std::string temp = dir; - if (need_slash) { - temp += "/"; - } - temp += filename_base; - - if (SystemTools::FileExists(temp)) { - res = true; - filename_found = temp; - } - - // If not found, we can try harder by appending part of the file to - // to the directory to look inside. - // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then - // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc. - - else if (try_filename_dirs) { - std::string filename_dir(filename); - std::string filename_dir_base; - std::string filename_dir_bases; - do { - filename_dir = SystemTools::GetFilenamePath(filename_dir); - filename_dir_base = SystemTools::GetFilenameName(filename_dir); -#if defined(_WIN32) - if (filename_dir_base.empty() || filename_dir_base.back() == ':') -#else - if (filename_dir_base.empty()) -#endif - { - break; - } - - filename_dir_bases = filename_dir_base + "/" + filename_dir_bases; - - temp = dir; - if (need_slash) { - temp += "/"; - } - temp += filename_dir_bases; - - res = SystemTools::LocateFileInDir(filename_base.c_str(), temp.c_str(), - filename_found, 0); - - } while (!res && !filename_dir_base.empty()); - } - } - - return res; -} - -bool SystemTools::FileIsFullPath(const std::string& in_name) -{ - return SystemToolsStatic::FileIsFullPath(in_name.c_str(), in_name.size()); -} - -bool SystemTools::FileIsFullPath(const char* in_name) -{ - return SystemToolsStatic::FileIsFullPath( - in_name, in_name[0] ? (in_name[1] ? 2 : 1) : 0); -} - -bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - // On Windows, the name must be at least two characters long. - if (len < 2) { - return false; - } - if (in_name[1] == ':') { - return true; - } - if (in_name[0] == '\\') { - return true; - } -#else - // On UNIX, the name must be at least one character long. - if (len < 1) { - return false; - } -#endif -#if !defined(_WIN32) - if (in_name[0] == '~') { - return true; - } -#endif - // On UNIX, the name must begin in a '/'. - // On Windows, if the name begins in a '/', then it is a full - // network path. - if (in_name[0] == '/') { - return true; - } - return false; -} - -bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath) -{ -#if defined(_WIN32) && !defined(__CYGWIN__) - std::string tempPath = path; // create a buffer - - // if the path passed in has quotes around it, first remove the quotes - if (!path.empty() && path[0] == '"' && path.back() == '"') { - tempPath = path.substr(1, path.length() - 2); - } - - std::wstring wtempPath = Encoding::ToWide(tempPath); - DWORD ret = GetShortPathNameW(wtempPath.c_str(), nullptr, 0); - std::vector<wchar_t> buffer(ret); - if (ret != 0) { - ret = GetShortPathNameW(wtempPath.c_str(), &buffer[0], - static_cast<DWORD>(buffer.size())); - } - - if (ret == 0) { - return false; - } else { - shortPath = Encoding::ToNarrow(&buffer[0]); - return true; - } -#else - shortPath = path; - return true; -#endif -} - -std::string SystemTools::GetCurrentDateTime(const char* format) -{ - char buf[1024]; - time_t t; - time(&t); - strftime(buf, sizeof(buf), format, localtime(&t)); - return std::string(buf); -} - -std::string SystemTools::MakeCidentifier(const std::string& s) -{ - std::string str(s); - if (str.find_first_of("0123456789") == 0) { - str = "_" + str; - } - - std::string permited_chars("_" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"); - std::string::size_type pos = 0; - while ((pos = str.find_first_not_of(permited_chars, pos)) != - std::string::npos) { - str[pos] = '_'; - } - return str; -} - -// Convenience function around std::getline which removes a trailing carriage -// return and can truncate the buffer as needed. Returns true -// if any data were read before the end-of-file was reached. -bool SystemTools::GetLineFromStream(std::istream& is, std::string& line, - bool* has_newline /* = 0 */, - long sizeLimit /* = -1 */) -{ - // Start with an empty line. - line = ""; - - // Early short circuit return if stream is no good. Just return - // false and the empty line. (Probably means caller tried to - // create a file stream with a non-existent file name...) - // - if (!is) { - if (has_newline) { - *has_newline = false; - } - return false; - } - - std::getline(is, line); - bool haveData = !line.empty() || !is.eof(); - if (!line.empty()) { - // Avoid storing a carriage return character. - if (line.back() == '\r') { - line.resize(line.size() - 1); - } - - // if we read too much then truncate the buffer - if (sizeLimit >= 0 && line.size() >= static_cast<size_t>(sizeLimit)) { - line.resize(sizeLimit); - } - } - - // Return the results. - if (has_newline) { - *has_newline = !is.eof(); - } - return haveData; -} - -int SystemTools::GetTerminalWidth() -{ - int width = -1; -#ifdef HAVE_TTY_INFO - struct winsize ws; - std::string columns; /* Unix98 environment variable */ - if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col > 0 && ws.ws_row > 0) { - width = ws.ws_col; - } - if (!isatty(STDOUT_FILENO)) { - width = -1; - } - if (SystemTools::GetEnv("COLUMNS", columns) && !columns.empty()) { - long t; - char* endptr; - t = strtol(columns.c_str(), &endptr, 0); - if (endptr && !*endptr && (t > 0) && (t < 1000)) { - width = static_cast<int>(t); - } - } - if (width < 9) { - width = -1; - } -#endif - return width; -} - -bool SystemTools::GetPermissions(const char* file, mode_t& mode) -{ - if (!file) { - return false; - } - return SystemTools::GetPermissions(std::string(file), mode); -} - -bool SystemTools::GetPermissions(const std::string& file, mode_t& mode) -{ -#if defined(_WIN32) - DWORD attr = - GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str()); - if (attr == INVALID_FILE_ATTRIBUTES) { - return false; - } - if ((attr & FILE_ATTRIBUTE_READONLY) != 0) { - mode = (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)); - } else { - mode = (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6)) | - (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)); - } - if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - mode |= S_IFDIR | (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)); - } else { - mode |= S_IFREG; - } - size_t dotPos = file.rfind('.'); - const char* ext = dotPos == std::string::npos ? 0 : (file.c_str() + dotPos); - if (ext && - (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 || - Strucmp(ext, ".cmd") == 0 || Strucmp(ext, ".bat") == 0)) { - mode |= (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)); - } -#else - struct stat st; - if (stat(file.c_str(), &st) < 0) { - return false; - } - mode = st.st_mode; -#endif - return true; -} - -bool SystemTools::SetPermissions(const char* file, mode_t mode, - bool honor_umask) -{ - if (!file) { - return false; - } - return SystemTools::SetPermissions(std::string(file), mode, honor_umask); -} - -bool SystemTools::SetPermissions(const std::string& file, mode_t mode, - bool honor_umask) -{ - if (!SystemTools::PathExists(file)) { - return false; - } - if (honor_umask) { - mode_t currentMask = umask(0); - umask(currentMask); - mode &= ~currentMask; - } -#ifdef _WIN32 - if (_wchmod(Encoding::ToWindowsExtendedPath(file).c_str(), mode) < 0) -#else - if (chmod(file.c_str(), mode) < 0) -#endif - { - return false; - } - - return true; -} - -std::string SystemTools::GetParentDirectory(const std::string& fileOrDir) -{ - return SystemTools::GetFilenamePath(fileOrDir); -} - -bool SystemTools::IsSubDirectory(const std::string& cSubdir, - const std::string& cDir) -{ - if (cDir.empty()) { - return false; - } - std::string subdir = cSubdir; - std::string dir = cDir; - SystemTools::ConvertToUnixSlashes(subdir); - SystemTools::ConvertToUnixSlashes(dir); - if (subdir.size() <= dir.size() || dir.empty()) { - return false; - } - bool isRootPath = dir.back() == '/'; // like "/" or "C:/" - size_t expectedSlashPosition = isRootPath ? dir.size() - 1u : dir.size(); - if (subdir[expectedSlashPosition] != '/') { - return false; - } - std::string s = subdir.substr(0, dir.size()); - return SystemTools::ComparePath(s, dir); -} - -void SystemTools::Delay(unsigned int msec) -{ -#ifdef _WIN32 - Sleep(msec); -#else - // The sleep function gives 1 second resolution and the usleep - // function gives 1e-6 second resolution but on some platforms has a - // maximum sleep time of 1 second. This could be re-implemented to - // use select with masked signals or pselect to mask signals - // atomically. If select is given empty sets and zero as the max - // file descriptor but a non-zero timeout it can be used to block - // for a precise amount of time. - if (msec >= 1000) { - sleep(msec / 1000); - usleep((msec % 1000) * 1000); - } else { - usleep(msec * 1000); - } -#endif -} - -std::string SystemTools::GetOperatingSystemNameAndVersion() -{ - std::string res; - -#ifdef _WIN32 - char buffer[256]; - - OSVERSIONINFOEXA osvi; - BOOL bOsVersionInfoEx; - - ZeroMemory(&osvi, sizeof(osvi)); - osvi.dwOSVersionInfoSize = sizeof(osvi); - -# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -# pragma warning(push) -# ifdef __INTEL_COMPILER -# pragma warning(disable : 1478) -# elif defined __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -# else -# pragma warning(disable : 4996) -# endif -# endif - bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA*)&osvi); - if (!bOsVersionInfoEx) { - return 0; - } -# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -# ifdef __clang__ -# pragma clang diagnostic pop -# else -# pragma warning(pop) -# endif -# endif - - switch (osvi.dwPlatformId) { - // Test for the Windows NT product family. - - case VER_PLATFORM_WIN32_NT: - - // Test for the specific product family. - if (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0) { - if (osvi.wProductType == VER_NT_WORKSTATION) { - res += "Microsoft Windows 10"; - } else { - res += "Microsoft Windows Server 2016 family"; - } - } - - if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) { - if (osvi.wProductType == VER_NT_WORKSTATION) { - res += "Microsoft Windows 8.1"; - } else { - res += "Microsoft Windows Server 2012 R2 family"; - } - } - - if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) { - if (osvi.wProductType == VER_NT_WORKSTATION) { - res += "Microsoft Windows 8"; - } else { - res += "Microsoft Windows Server 2012 family"; - } - } - - if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) { - if (osvi.wProductType == VER_NT_WORKSTATION) { - res += "Microsoft Windows 7"; - } else { - res += "Microsoft Windows Server 2008 R2 family"; - } - } - - if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) { - if (osvi.wProductType == VER_NT_WORKSTATION) { - res += "Microsoft Windows Vista"; - } else { - res += "Microsoft Windows Server 2008 family"; - } - } - - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { - res += "Microsoft Windows Server 2003 family"; - } - - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { - res += "Microsoft Windows XP"; - } - - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) { - res += "Microsoft Windows 2000"; - } - - if (osvi.dwMajorVersion <= 4) { - res += "Microsoft Windows NT"; - } - - // Test for specific product on Windows NT 4.0 SP6 and later. - - if (bOsVersionInfoEx) { - // Test for the workstation type. - - if (osvi.wProductType == VER_NT_WORKSTATION) { - if (osvi.dwMajorVersion == 4) { - res += " Workstation 4.0"; - } else if (osvi.dwMajorVersion == 5) { - if (osvi.wSuiteMask & VER_SUITE_PERSONAL) { - res += " Home Edition"; - } else { - res += " Professional"; - } - } - } - - // Test for the server type. - - else if (osvi.wProductType == VER_NT_SERVER) { - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) { - res += " Datacenter Edition"; - } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) { - res += " Enterprise Edition"; - } else if (osvi.wSuiteMask == VER_SUITE_BLADE) { - res += " Web Edition"; - } else { - res += " Standard Edition"; - } - } - - else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) { - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) { - res += " Datacenter Server"; - } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) { - res += " Advanced Server"; - } else { - res += " Server"; - } - } - - else if (osvi.dwMajorVersion <= 4) // Windows NT 4.0 - { - if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) { - res += " Server 4.0, Enterprise Edition"; - } else { - res += " Server 4.0"; - } - } - } - } - - // Test for specific product on Windows NT 4.0 SP5 and earlier - - else { - HKEY hKey; -# define BUFSIZE 80 - wchar_t szProductType[BUFSIZE]; - DWORD dwBufLen = BUFSIZE; - LONG lRet; - - lRet = - RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", - 0, KEY_QUERY_VALUE, &hKey); - if (lRet != ERROR_SUCCESS) { - return 0; - } - - lRet = RegQueryValueExW(hKey, L"ProductType", nullptr, nullptr, - (LPBYTE)szProductType, &dwBufLen); - - if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE)) { - return 0; - } - - RegCloseKey(hKey); - - if (lstrcmpiW(L"WINNT", szProductType) == 0) { - res += " Workstation"; - } - if (lstrcmpiW(L"LANMANNT", szProductType) == 0) { - res += " Server"; - } - if (lstrcmpiW(L"SERVERNT", szProductType) == 0) { - res += " Advanced Server"; - } - - res += " "; - sprintf(buffer, "%ld", osvi.dwMajorVersion); - res += buffer; - res += "."; - sprintf(buffer, "%ld", osvi.dwMinorVersion); - res += buffer; - } - - // Display service pack (if any) and build number. - - if (osvi.dwMajorVersion == 4 && - lstrcmpiA(osvi.szCSDVersion, "Service Pack 6") == 0) { - HKEY hKey; - LONG lRet; - - // Test for SP6 versus SP6a. - - lRet = RegOpenKeyExW( - HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", - 0, KEY_QUERY_VALUE, &hKey); - - if (lRet == ERROR_SUCCESS) { - res += " Service Pack 6a (Build "; - sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF); - res += buffer; - res += ")"; - } else // Windows NT 4.0 prior to SP6a - { - res += " "; - res += osvi.szCSDVersion; - res += " (Build "; - sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF); - res += buffer; - res += ")"; - } - - RegCloseKey(hKey); - } else // Windows NT 3.51 and earlier or Windows 2000 and later - { - res += " "; - res += osvi.szCSDVersion; - res += " (Build "; - sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF); - res += buffer; - res += ")"; - } - - break; - - // Test for the Windows 95 product family. - - case VER_PLATFORM_WIN32_WINDOWS: - - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) { - res += "Microsoft Windows 95"; - if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') { - res += " OSR2"; - } - } - - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) { - res += "Microsoft Windows 98"; - if (osvi.szCSDVersion[1] == 'A') { - res += " SE"; - } - } - - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) { - res += "Microsoft Windows Millennium Edition"; - } - break; - - case VER_PLATFORM_WIN32s: - - res += "Microsoft Win32s"; - break; - } -#endif - - return res; -} - -bool SystemTools::ParseURLProtocol(const std::string& URL, - std::string& protocol, - std::string& dataglom) -{ - // match 0 entire url - // match 1 protocol - // match 2 dataglom following protocol:// - kwsys::RegularExpression urlRe(VTK_URL_PROTOCOL_REGEX); - - if (!urlRe.find(URL)) - return false; - - protocol = urlRe.match(1); - dataglom = urlRe.match(2); - - return true; -} - -bool SystemTools::ParseURL(const std::string& URL, std::string& protocol, - std::string& username, std::string& password, - std::string& hostname, std::string& dataport, - std::string& database) -{ - kwsys::RegularExpression urlRe(VTK_URL_REGEX); - if (!urlRe.find(URL)) - return false; - - // match 0 URL - // match 1 protocol - // match 2 mangled user - // match 3 username - // match 4 mangled password - // match 5 password - // match 6 hostname - // match 7 mangled port - // match 8 dataport - // match 9 database name - - protocol = urlRe.match(1); - username = urlRe.match(3); - password = urlRe.match(5); - hostname = urlRe.match(6); - dataport = urlRe.match(8); - database = urlRe.match(9); - - return true; -} - -// These must NOT be initialized. Default initialization to zero is -// necessary. -static unsigned int SystemToolsManagerCount; -SystemToolsStatic* SystemTools::Statics; - -// SystemToolsManager manages the SystemTools singleton. -// SystemToolsManager should be included in any translation unit -// that will use SystemTools or that implements the singleton -// pattern. It makes sure that the SystemTools singleton is created -// before and destroyed after all other singletons in CMake. - -SystemToolsManager::SystemToolsManager() -{ - if (++SystemToolsManagerCount == 1) { - SystemTools::ClassInitialize(); - } -} - -SystemToolsManager::~SystemToolsManager() -{ - if (--SystemToolsManagerCount == 0) { - SystemTools::ClassFinalize(); - } -} - -#if defined(__VMS) -// On VMS we configure the run time C library to be more UNIX like. -// http://h71000.www7.hp.com/doc/732final/5763/5763pro_004.html -extern "C" int decc$feature_get_index(char* name); -extern "C" int decc$feature_set_value(int index, int mode, int value); -static int SetVMSFeature(char* name, int value) -{ - int i; - errno = 0; - i = decc$feature_get_index(name); - return i >= 0 && (decc$feature_set_value(i, 1, value) >= 0 || errno == 0); -} -#endif - -void SystemTools::ClassInitialize() -{ -#ifdef __VMS - SetVMSFeature("DECC$FILENAME_UNIX_ONLY", 1); -#endif - - // Create statics singleton instance - SystemTools::Statics = new SystemToolsStatic; - -#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP -// Add some special translation paths for unix. These are not added -// for windows because drive letters need to be maintained. Also, -// there are not sym-links and mount points on windows anyway. -# if !defined(_WIN32) || defined(__CYGWIN__) - // The tmp path is frequently a logical path so always keep it: - SystemTools::AddKeepPath("/tmp/"); - - // If the current working directory is a logical path then keep the - // logical name. - std::string pwd_str; - if (SystemTools::GetEnv("PWD", pwd_str)) { - char buf[2048]; - if (const char* cwd = Getcwd(buf, 2048)) { - // The current working directory may be a logical path. Find - // the shortest logical path that still produces the correct - // physical path. - std::string cwd_changed; - std::string pwd_changed; - - // Test progressively shorter logical-to-physical mappings. - std::string cwd_str = cwd; - std::string pwd_path; - Realpath(pwd_str, pwd_path); - while (cwd_str == pwd_path && cwd_str != pwd_str) { - // The current pair of paths is a working logical mapping. - cwd_changed = cwd_str; - pwd_changed = pwd_str; - - // Strip off one directory level and see if the logical - // mapping still works. - pwd_str = SystemTools::GetFilenamePath(pwd_str); - cwd_str = SystemTools::GetFilenamePath(cwd_str); - Realpath(pwd_str, pwd_path); - } - - // Add the translation to keep the logical path name. - if (!cwd_changed.empty() && !pwd_changed.empty()) { - SystemTools::AddTranslationPath(cwd_changed, pwd_changed); - } - } - } -# endif -#endif -} - -void SystemTools::ClassFinalize() -{ - delete SystemTools::Statics; -} - -} // namespace KWSYS_NAMESPACE - -#if defined(_MSC_VER) && defined(_DEBUG) -# include <crtdbg.h> -# include <stdio.h> -# include <stdlib.h> -namespace KWSYS_NAMESPACE { - -static int SystemToolsDebugReport(int, char* message, int*) -{ - fprintf(stderr, "%s", message); - fflush(stderr); - return 1; // no further reporting required -} - -void SystemTools::EnableMSVCDebugHook() -{ - if (SystemTools::HasEnv("DART_TEST_FROM_DART") || - SystemTools::HasEnv("DASHBOARD_TEST_FROM_CTEST")) { - _CrtSetReportHook(SystemToolsDebugReport); - } -} - -} // namespace KWSYS_NAMESPACE -#else -namespace KWSYS_NAMESPACE { -void SystemTools::EnableMSVCDebugHook() -{ -} -} // namespace KWSYS_NAMESPACE -#endif |