diff options
author | Brad King <brad.king@kitware.com> | 2003-04-08 17:10:44 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2003-04-08 17:10:44 (GMT) |
commit | 7dff3a7f69d1ec1e36d38903e94e433f6583d96e (patch) | |
tree | 52188fec4a7e35d1fd08e3ed6c3dcfbf1095a818 /Source/kwsys/SystemTools.cxx | |
parent | 7f48313225537a7bcc92c0f1c73754bdc50a2ca4 (diff) | |
download | CMake-7dff3a7f69d1ec1e36d38903e94e433f6583d96e.zip CMake-7dff3a7f69d1ec1e36d38903e94e433f6583d96e.tar.gz CMake-7dff3a7f69d1ec1e36d38903e94e433f6583d96e.tar.bz2 |
ENH: Added kwsys library for platform-independent system tools.
Diffstat (limited to 'Source/kwsys/SystemTools.cxx')
-rw-r--r-- | Source/kwsys/SystemTools.cxx | 1793 |
1 files changed, 1793 insertions, 0 deletions
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx new file mode 100644 index 0000000..fca3f46 --- /dev/null +++ b/Source/kwsys/SystemTools.cxx @@ -0,0 +1,1793 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include <SystemTools.hxx> +#include <RegularExpression.hxx> +#include <Directory.hxx> + +#include <fstream> + +#include <stdio.h> +#include <sys/stat.h> +#include <ctype.h> +#include <errno.h> +#include <time.h> + +// support for realpath call +#ifndef _WIN32 +#include <limits.h> +#include <stdlib.h> +#include <sys/param.h> +#include <sys/wait.h> +#endif + +#if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__)) +#include <string.h> +#include <windows.h> +#include <direct.h> +#define _unlink unlink +inline int Mkdir(const char* dir) +{ + return _mkdir(dir); +} +inline const char* Getcwd(char* buf, unsigned int len) +{ + return _getcwd(buf, len); +} +inline int Chdir(const char* dir) +{ + #if defined(__BORLANDC__) + return chdir(dir); + #else + return _chdir(dir); + #endif +} +#else +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +inline int Mkdir(const char* dir) +{ + return mkdir(dir, 00777); +} +inline const char* Getcwd(char* buf, unsigned int len) +{ + return getcwd(buf, len); +} +inline int Chdir(const char* dir) +{ + return chdir(dir); +} +#endif + + +/* Implement floattime() for various platforms */ +// Taken from Python 2.1.3 + +#if defined( _WIN32 ) && !defined( __CYGWIN__ ) +# include <sys/timeb.h> +# define HAVE_FTIME +# if defined( __BORLANDC__) +# define FTIME ftime +# define TIMEB timeb +# else // Visual studio? +# define FTIME _ftime +# define TIMEB _timeb +# endif +#elif defined( __CYGWIN__ ) || defined( __linux__ ) +# include <sys/time.h> +# include <time.h> +# define HAVE_GETTIMEOFDAY +#endif + +namespace KWSYS_NAMESPACE +{ + +double +SystemTools::GetTime(void) +{ + /* There are three ways to get the time: + (1) gettimeofday() -- resolution in microseconds + (2) ftime() -- resolution in milliseconds + (3) time() -- resolution in seconds + In all cases the return value is a float in seconds. + Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may + fail, so we fall back on ftime() or time(). + Note: clock resolution does not imply clock accuracy! */ +#ifdef HAVE_GETTIMEOFDAY + { + struct timeval t; +#ifdef GETTIMEOFDAY_NO_TZ + if (gettimeofday(&t) == 0) + return (double)t.tv_sec + t.tv_usec*0.000001; +#else /* !GETTIMEOFDAY_NO_TZ */ + if (gettimeofday(&t, (struct timezone *)NULL) == 0) + return (double)t.tv_sec + t.tv_usec*0.000001; +#endif /* !GETTIMEOFDAY_NO_TZ */ + } +#endif /* !HAVE_GETTIMEOFDAY */ + { +#if defined(HAVE_FTIME) + struct TIMEB t; + FTIME(&t); + return (double)t.time + (double)t.millitm * (double)0.001; +#else /* !HAVE_FTIME */ + time_t secs; + time(&secs); + return (double)secs; +#endif /* !HAVE_FTIME */ + } +} + +// adds the elements of the env variable path to the arg passed in +void SystemTools::GetPath(kwsys_std::vector<kwsys_std::string>& path) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + const char* pathSep = ";"; +#else + const char* pathSep = ":"; +#endif + kwsys_std::string pathEnv = getenv("PATH"); + // A hack to make the below algorithm work. + if(pathEnv[pathEnv.length()-1] != ':') + { + pathEnv += pathSep; + } + kwsys_std::string::size_type start =0; + bool done = false; + while(!done) + { + kwsys_std::string::size_type endpos = pathEnv.find(pathSep, start); + if(endpos != kwsys_std::string::npos) + { + path.push_back(pathEnv.substr(start, endpos-start)); + start = endpos+1; + } + else + { + done = true; + } + } + for(kwsys_std::vector<kwsys_std::string>::iterator i = path.begin(); + i != path.end(); ++i) + { + SystemTools::ConvertToUnixSlashes(*i); + } +} + + +const char* SystemTools::GetExecutableExtension() +{ +#if defined(_WIN32) || defined(__CYGWIN__) + return ".exe"; +#else + return ""; +#endif +} + + +bool SystemTools::MakeDirectory(const char* path) +{ + if(SystemTools::FileExists(path)) + { + return true; + } + kwsys_std::string dir = path; + if(dir.size() == 0) + { + return false; + } + SystemTools::ConvertToUnixSlashes(dir); + + kwsys_std::string::size_type pos = dir.find(':'); + if(pos == kwsys_std::string::npos) + { + pos = 0; + } + kwsys_std::string topdir; + while((pos = dir.find('/', pos)) != kwsys_std::string::npos) + { + topdir = dir.substr(0, pos); + Mkdir(topdir.c_str()); + pos++; + } + if(dir[dir.size()-1] == '/') + { + topdir = dir.substr(0, dir.size()); + } + else + { + topdir = dir; + } + if(Mkdir(topdir.c_str()) != 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; + } + } + return true; +} + + +// replace replace with with as many times as it shows up in source. +// write the result into source. +void SystemTools::ReplaceString(kwsys_std::string& source, + const char* replace, + const char* with) +{ + // get out quick if string is not found + kwsys_std::string::size_type start = source.find(replace); + if(start == kwsys_std::string::npos) + { + return; + } + kwsys_std::string rest; + kwsys_std::string::size_type lengthReplace = strlen(replace); + kwsys_std::string::size_type lengthWith = strlen(with); + while(start != kwsys_std::string::npos) + { + rest = source.substr(start+lengthReplace); + source = source.substr(0, start); + source += with; + source += rest; + start = source.find(replace, start + lengthWith ); + } +} + +// 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 char *key, kwsys_std::string &value) +{ + + kwsys_std::string primary = key; + kwsys_std::string second; + kwsys_std::string valuename; + + size_t start = primary.find("\\"); + if (start == kwsys_std::string::npos) + { + return false; + } + + size_t valuenamepos = primary.find(";"); + if (valuenamepos != kwsys_std::string::npos) + { + valuename = primary.substr(valuenamepos+1); + } + + second = primary.substr(start+1, valuenamepos-start-1); + primary = primary.substr(0, start); + + HKEY primaryKey; + 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; + } + + HKEY hKey; + if(RegOpenKeyEx(primaryKey, + second.c_str(), + 0, + KEY_READ, + &hKey) != ERROR_SUCCESS) + { + return false; + } + else + { + DWORD dwType, dwSize; + dwSize = 1023; + char data[1024]; + if(RegQueryValueEx(hKey, + (LPTSTR)valuename.c_str(), + NULL, + &dwType, + (BYTE *)data, + &dwSize) == ERROR_SUCCESS) + { + if (dwType == REG_SZ) + { + value = data; + return true; + } + } + } + return false; +} +#else +bool SystemTools::ReadRegistryValue(const char *, kwsys_std::string &) +{ + 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 char *key, const char *value) +{ + kwsys_std::string primary = key; + kwsys_std::string second; + kwsys_std::string valuename; + + size_t start = primary.find("\\"); + if (start == kwsys_std::string::npos) + { + return false; + } + + size_t valuenamepos = primary.find(";"); + if (valuenamepos != kwsys_std::string::npos) + { + valuename = primary.substr(valuenamepos+1); + } + + second = primary.substr(start+1, valuenamepos-start-1); + primary = primary.substr(0, start); + + HKEY primaryKey; + 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; + } + + HKEY hKey; + DWORD dwDummy; + if(RegCreateKeyEx(primaryKey, + second.c_str(), + 0, + "", + REG_OPTION_NON_VOLATILE, + KEY_WRITE, + NULL, + &hKey, + &dwDummy) != ERROR_SUCCESS) + { + return false; + } + + if(RegSetValueEx(hKey, + (LPTSTR)valuename.c_str(), + 0, + REG_SZ, + (CONST BYTE *)value, + (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS) + { + return true; + } + return false; +} +#else +bool SystemTools::WriteRegistryValue(const char *, const char *) +{ + 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 char *key) +{ + kwsys_std::string primary = key; + kwsys_std::string second; + kwsys_std::string valuename; + + size_t start = primary.find("\\"); + if (start == kwsys_std::string::npos) + { + return false; + } + + size_t valuenamepos = primary.find(";"); + if (valuenamepos != kwsys_std::string::npos) + { + valuename = primary.substr(valuenamepos+1); + } + + second = primary.substr(start+1, valuenamepos-start-1); + primary = primary.substr(0, start); + + HKEY primaryKey; + 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; + } + + HKEY hKey; + if(RegOpenKeyEx(primaryKey, + second.c_str(), + 0, + KEY_WRITE, + &hKey) != ERROR_SUCCESS) + { + return false; + } + else + { + if(RegDeleteValue(hKey, + (LPTSTR)valuename.c_str()) == ERROR_SUCCESS) + { + return true; + } + } + return false; +} +#else +bool SystemTools::DeleteRegistryValue(const char *) +{ + return false; +} +#endif + +// replace replace with with as many times as it shows up in source. +// write the result into source. +#if defined(_WIN32) && !defined(__CYGWIN__) +void SystemTools::ExpandRegistryValues(kwsys_std::string& source) +{ + // Regular expression to match anything inside [...] that begins in HKEY. + // Note that there is a special rule for regular expressions to match a + // close square-bracket inside a list delimited by square brackets. + // The "[^]]" part of this expression will match any character except + // a close square-bracket. The ']' character must be the first in the + // list of characters inside the [^...] block of the expression. + cmRegularExpression regEntry("\\[(HKEY[^]]*)\\]"); + + // check for black line or comment + while (regEntry.find(source)) + { + // the arguments are the second match + kwsys_std::string key = regEntry.match(1); + kwsys_std::string val; + if (ReadRegistryValue(key.c_str(), val)) + { + kwsys_std::string reg = "["; + reg += key + "]"; + SystemTools::ReplaceString(source, reg.c_str(), val.c_str()); + } + else + { + kwsys_std::string reg = "["; + reg += key + "]"; + SystemTools::ReplaceString(source, reg.c_str(), "/registry"); + } + } +} +#else +void SystemTools::ExpandRegistryValues(kwsys_std::string&) +{ +} +#endif + + +kwsys_std::string SystemTools::EscapeQuotes(const char* str) +{ + kwsys_std::string result = ""; + for(const char* ch = str; *ch != '\0'; ++ch) + { + if(*ch == '"') + { + result += '\\'; + } + result += *ch; + } + return result; +} + +bool SystemTools::SameFile(const char* file1, const char* file2) +{ +#ifdef _WIN32 + HANDLE hFile1, hFile2; + + hFile1 = CreateFile( file1, + GENERIC_READ, + FILE_SHARE_READ , + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + hFile2 = CreateFile( file2, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + 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.nFileIndexHigh == fiBuf2.nFileIndexHigh && + fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow); +#else + struct stat fileStat1, fileStat2; + if (stat(file1, &fileStat1) == 0 && stat(file2, &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 +} + + +// return true if the file exists +bool SystemTools::FileExists(const char* filename) +{ + struct stat fs; + if (stat(filename, &fs) != 0) + { + return false; + } + else + { + return true; + } +} + + +// Return a capitalized string (i.e the first letter is uppercased, all other +// are lowercased) +kwsys_std::string SystemTools::Capitalized(const kwsys_std::string& s) +{ + kwsys_std::string n; + n.resize(s.size()); + n[0] = toupper(s[0]); + for (size_t i = 1; i < s.size(); i++) + { + n[i] = tolower(s[i]); + } + return n; +} + + +// Return a lower case string +kwsys_std::string SystemTools::LowerCase(const kwsys_std::string& s) +{ + kwsys_std::string n; + n.resize(s.size()); + for (size_t i = 0; i < s.size(); i++) + { + n[i] = tolower(s[i]); + } + return n; +} + +// Return a lower case string +kwsys_std::string SystemTools::UpperCase(const kwsys_std::string& s) +{ + kwsys_std::string n; + n.resize(s.size()); + for (size_t i = 0; i < s.size(); i++) + { + n[i] = toupper(s[i]); + } + return n; +} + + +// convert windows slashes to unix slashes +void SystemTools::ConvertToUnixSlashes(kwsys_std::string& path) +{ + kwsys_std::string::size_type pos = 0; + while((pos = path.find('\\', pos)) != kwsys_std::string::npos) + { + path[pos] = '/'; + pos++; + } + // Remove all // from the path just like most unix shells + int start_find = 0; + +#ifdef _WIN32 + // However, on windows if the first characters are both slashes, + // then keep them that way, so that network paths can be handled. + start_find = 1; +#endif + + while((pos = path.find("//", start_find)) != kwsys_std::string::npos) + { + SystemTools::ReplaceString(path, "//", "/"); + } + + // remove any trailing slash + if(path.size() && path[path.size()-1] == '/') + { + path = path.substr(0, path.size()-1); + } + + // if there is a tilda ~ then replace it with HOME + if(path.find("~") == 0) + { + if (getenv("HOME")) + { + path = kwsys_std::string(getenv("HOME")) + path.substr(1); + } + } + + // if there is a /tmp_mnt in a path get rid of it! + // stupid sgi's + if(path.find("/tmp_mnt") == 0) + { + path = path.substr(8); + } +} + + +// change // to /, and escape any spaces in the path +kwsys_std::string SystemTools::ConvertToUnixOutputPath(const char* path) +{ + kwsys_std::string ret = path; + + // remove // except at the beginning might be a cygwin drive + kwsys_std::string::size_type pos = 1; + while((pos = ret.find("//", pos)) != kwsys_std::string::npos) + { + ret.erase(pos, 1); + } + // now escape spaces if there is a space in the path + if(ret.find(" ") != kwsys_std::string::npos) + { + kwsys_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; +} + + + +kwsys_std::string SystemTools::EscapeSpaces(const char* str) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + kwsys_std::string result; + + // if there are spaces + kwsys_std::string temp = str; + if (temp.find(" ") != kwsys_std::string::npos && + temp.find("\"")==kwsys_std::string::npos) + { + result = "\""; + result += str; + result += "\""; + return result; + } + return str; +#else + kwsys_std::string result = ""; + for(const char* ch = str; *ch != '\0'; ++ch) + { + if(*ch == ' ') + { + result += '\\'; + } + result += *ch; + } + return result; +#endif +} + +kwsys_std::string SystemTools::ConvertToOutputPath(const char* path) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + return SystemTools::ConvertToWindowsOutputPath(path); +#else + return SystemTools::ConvertToUnixOutputPath(path); +#endif +} + + +// remove double slashes not at the start +kwsys_std::string SystemTools::ConvertToWindowsOutputPath(const char* path) +{ + kwsys_std::string ret = path; + kwsys_std::string::size_type pos = 0; + // first convert all of the slashes + while((pos = ret.find('/', pos)) != kwsys_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)) != kwsys_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(" ") != kwsys_std::string::npos + && ret[0] != '\"') + { + kwsys_std::string result; + result = "\"" + ret + "\""; + ret = result; + } + return ret; +} + +bool SystemTools::CopyFileIfDifferent(const char* source, + const char* destination) +{ + if(SystemTools::FilesDiffer(source, destination)) + { + SystemTools::CopyFileAlways(source, destination); + return true; + } + return false; +} + + +bool SystemTools::FilesDiffer(const char* source, + const char* destination) +{ + struct stat statSource; + if (stat(source, &statSource) != 0) + { + return true; + } + + struct stat statDestination; + if (stat(destination, &statDestination) != 0) + { + return true; + } + + if(statSource.st_size != statDestination.st_size) + { + return true; + } + + if(statSource.st_size == 0) + { + return false; + } + +#if defined(_WIN32) || defined(__CYGWIN__) + kwsys_std::ifstream finSource(source, + kwsys_std::ios::binary | kwsys_std::ios::in); + kwsys_std::ifstream finDestination(destination, + kwsys_std::ios::binary | kwsys_std::ios::in); +#else + kwsys_std::ifstream finSource(source); + kwsys_std::ifstream finDestination(destination); +#endif + if(!finSource || !finDestination) + { + return true; + } + + char* source_buf = new char[statSource.st_size]; + char* dest_buf = new char[statSource.st_size]; + + finSource.read(source_buf, statSource.st_size); + finDestination.read(dest_buf, statSource.st_size); + + if(statSource.st_size != static_cast<long>(finSource.gcount()) || + statSource.st_size != static_cast<long>(finDestination.gcount())) + { + // Failed to read files. + delete [] source_buf; + delete [] dest_buf; + return true; + } + int ret = memcmp((const void*)source_buf, + (const void*)dest_buf, + statSource.st_size); + + delete [] dest_buf; + delete [] source_buf; + + return ret != 0; +} + + +/** + * Copy a file named by "source" to the file named by "destination". + */ +bool SystemTools::CopyFileAlways(const char* source, const char* destination) +{ + const int bufferSize = 4096; + char buffer[bufferSize]; + + // If destination is a directory, try to create a file with the same + // name as the source in that directory. + + kwsys_std::string new_destination; + if(SystemTools::FileExists(destination) && + SystemTools::FileIsDirectory(destination)) + { + new_destination = destination; + SystemTools::ConvertToUnixSlashes(new_destination); + new_destination += '/'; + kwsys_std::string source_name = source; + new_destination += SystemTools::GetFilenameName(source_name); + destination = new_destination.c_str(); + } + + // Create destination directory + + kwsys_std::string destination_dir = destination; + destination_dir = SystemTools::GetFilenamePath(destination_dir); + SystemTools::MakeDirectory(destination_dir.c_str()); + + // Open files + +#if defined(_WIN32) || defined(__CYGWIN__) + kwsys_std::ifstream fin(source, + kwsys_std::ios::binary | kwsys_std::ios::in); +#else + kwsys_std::ifstream fin(source); +#endif + if(!fin) + { + return false; + } + +#if defined(_WIN32) || defined(__CYGWIN__) + kwsys_std::ofstream fout(destination, + kwsys_std::ios::binary | kwsys_std::ios::out | kwsys_std::ios::trunc); +#else + kwsys_std::ofstream fout(destination, + kwsys_std::ios::out | kwsys_std::ios::trunc); +#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) + { + fin.read(buffer, bufferSize); + if(fin.gcount()) + { + fout.write(buffer, fin.gcount()); + } + } + + // 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(); + + // More checks. + struct stat statSource, statDestination; + statSource.st_size = 12345; + statDestination.st_size = 12345; + if(stat(source, &statSource) != 0) + { + return false; + } + else if(stat(destination, &statDestination) != 0) + { + return false; + } + else if(statSource.st_size != statDestination.st_size) + { + return false; + } + return true; +} + +// return true if the file exists +long int SystemTools::ModifiedTime(const char* filename) +{ + struct stat fs; + if (stat(filename, &fs) != 0) + { + return 0; + } + else + { + return (long int)fs.st_mtime; + } +} + + +kwsys_std::string SystemTools::GetLastSystemError() +{ + int e = errno; + return strerror(e); +} + +bool SystemTools::RemoveFile(const char* source) +{ + return unlink(source) != 0 ? false : true; +} + +/** + * 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. + */ +kwsys_std::string SystemTools::FindFile(const char* name, + const kwsys_std::vector<kwsys_std::string>& userPaths) +{ + // Add the system search path to our path. + kwsys_std::vector<kwsys_std::string> path = userPaths; + SystemTools::GetPath(path); + + kwsys_std::string tryPath; + for(kwsys_std::vector<kwsys_std::string>::const_iterator p = path.begin(); + p != path.end(); ++p) + { + tryPath = *p; + tryPath += "/"; + tryPath += name; + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + } + // 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. + */ +kwsys_std::string SystemTools::FindProgram(const char* name, + const kwsys_std::vector<kwsys_std::string>& userPaths, + bool no_system_path) +{ + if(!name) + { + return ""; + } + // See if the executable exists as written. + if(SystemTools::FileExists(name) && + !SystemTools::FileIsDirectory(name)) + { + return SystemTools::CollapseFullPath(name); + } + kwsys_std::string tryPath = name; + tryPath += SystemTools::GetExecutableExtension(); + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + + // Add the system search path to our path. + kwsys_std::vector<kwsys_std::string> path = userPaths; + if (!no_system_path) + { + SystemTools::GetPath(path); + } + + for(kwsys_std::vector<kwsys_std::string>::const_iterator p = path.begin(); + p != path.end(); ++p) + { + tryPath = *p; + tryPath += "/"; + tryPath += name; + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } +#ifdef _WIN32 + tryPath += ".com"; + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/"; + tryPath += name; +#endif + tryPath += SystemTools::GetExecutableExtension(); + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + } + + // Couldn't find the program. + 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. + */ +kwsys_std::string SystemTools::FindLibrary(const char* name, + const kwsys_std::vector<kwsys_std::string>& userPaths) +{ + // See if the executable exists as written. + if(SystemTools::FileExists(name) && + !SystemTools::FileIsDirectory(name)) + { + return SystemTools::CollapseFullPath(name); + } + + // Add the system search path to our path. + kwsys_std::vector<kwsys_std::string> path = userPaths; + SystemTools::GetPath(path); + + kwsys_std::string tryPath; + for(kwsys_std::vector<kwsys_std::string>::const_iterator p = path.begin(); + p != path.end(); ++p) + { +#if defined(_WIN32) && !defined(__CYGWIN__) + tryPath = *p; + tryPath += "/"; + tryPath += name; + tryPath += ".lib"; + if(SystemTools::FileExists(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } +#else + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".so"; + if(SystemTools::FileExists(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".a"; + if(SystemTools::FileExists(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".sl"; + if(SystemTools::FileExists(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".dylib"; + if(SystemTools::FileExists(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } +#endif + } + + // Couldn't find the library. + return ""; +} + +bool SystemTools::FileIsDirectory(const char* name) +{ + struct stat fs; + if(stat(name, &fs) == 0) + { +#if _WIN32 + return ((fs.st_mode & _S_IFDIR) != 0); +#else + return S_ISDIR(fs.st_mode); +#endif + } + else + { + return false; + } +} + +int SystemTools::ChangeDirectory(const char *dir) +{ + return Chdir(dir); +} + +kwsys_std::string SystemTools::GetCurrentWorkingDirectory() +{ + char buf[2048]; + kwsys_std::string path = Getcwd(buf, 2048); + return path; +} + +kwsys_std::string SystemTools::GetProgramPath(const char* in_name) +{ + kwsys_std::string dir, file; + SystemTools::SplitProgramPath(in_name, dir, file); + return dir; +} + +bool SystemTools::SplitProgramPath(const char* in_name, + kwsys_std::string& dir, + kwsys_std::string& file, + bool errorReport) +{ + dir = in_name; + file = ""; + SystemTools::ConvertToUnixSlashes(dir); + + if(!SystemTools::FileIsDirectory(dir.c_str())) + { + kwsys_std::string::size_type slashPos = dir.rfind("/"); + if(slashPos != kwsys_std::string::npos) + { + file = dir.substr(slashPos+1); + dir = dir.substr(0, slashPos); + } + else + { + file = dir; + dir = ""; + } + } + if((dir != "") && !SystemTools::FileIsDirectory(dir.c_str())) + { + kwsys_std::string oldDir = in_name; + SystemTools::ConvertToUnixSlashes(oldDir); + dir = in_name; + return false; + } + return true; +} + +kwsys_std::string SystemTools::CollapseFullPath(const char* in_relative) +{ + return SystemTools::CollapseFullPath(in_relative, 0); +} + +kwsys_std::string SystemTools::CollapseFullPath(const char* in_relative, + const char* in_base) +{ + kwsys_std::string dir, file; + SystemTools::SplitProgramPath(in_relative, dir, file, false); + + // Save original working directory. + kwsys_std::string orig = SystemTools::GetCurrentWorkingDirectory(); + + // Change to base of relative path. + if(in_base) + { + Chdir(in_base); + } + +#ifdef _WIN32 + // Follow relative path. + if(dir != "") + { + Chdir(dir.c_str()); + } + + // Get the resulting directory. + kwsys_std::string newDir = SystemTools::GetCurrentWorkingDirectory(); + + // Add the file back on to the directory. + SystemTools::ConvertToUnixSlashes(newDir); +#else +# ifdef MAXPATHLEN + char resolved_name[MAXPATHLEN]; +# else +# ifdef PATH_MAX + char resolved_name[PATH_MAX]; +# else + char resolved_name[5024]; +# endif +# endif + + // Resolve relative path. + kwsys_std::string newDir; + if(dir != "") + { + realpath(dir.c_str(), resolved_name); + newDir = resolved_name; + } + else + { + newDir = SystemTools::GetCurrentWorkingDirectory(); + } +#endif + + // Restore original working directory. + Chdir(orig.c_str()); + + // Construct and return the full path. + kwsys_std::string newPath = newDir; + if(file != "") + { + newPath += "/"; + newPath += file; + } + return newPath; +} + +bool SystemTools::Split(const char* str, kwsys_std::vector<kwsys_std::string>& lines) +{ + kwsys_std::string data(str); + kwsys_std::string::size_type lpos = 0; + while(lpos < data.length()) + { + kwsys_std::string::size_type rpos = data.find_first_of("\n", lpos); + if(rpos == kwsys_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. + */ +kwsys_std::string SystemTools::GetFilenamePath(const kwsys_std::string& filename) +{ + kwsys_std::string fn = filename; + SystemTools::ConvertToUnixSlashes(fn); + + kwsys_std::string::size_type slash_pos = fn.rfind("/"); + if(slash_pos != kwsys_std::string::npos) + { + return fn.substr(0, slash_pos); + } + else + { + return ""; + } +} + + +/** + * Return file name of a full filename (i.e. file name without path). + */ +kwsys_std::string SystemTools::GetFilenameName(const kwsys_std::string& filename) +{ + kwsys_std::string fn = filename; + SystemTools::ConvertToUnixSlashes(fn); + + kwsys_std::string::size_type slash_pos = fn.rfind("/"); + if(slash_pos != kwsys_std::string::npos) + { + return fn.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) + */ +kwsys_std::string SystemTools::GetFilenameExtension(const kwsys_std::string& filename) +{ + kwsys_std::string name = SystemTools::GetFilenameName(filename); + kwsys_std::string::size_type dot_pos = name.find("."); + if(dot_pos != kwsys_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) + */ +kwsys_std::string SystemTools::GetFilenameWithoutExtension(const kwsys_std::string& filename) +{ + kwsys_std::string name = SystemTools::GetFilenameName(filename); + kwsys_std::string::size_type dot_pos = name.find("."); + if(dot_pos != kwsys_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) + */ +kwsys_std::string +SystemTools::GetFilenameWithoutLastExtension(const kwsys_std::string& filename) +{ + kwsys_std::string name = SystemTools::GetFilenameName(filename); + kwsys_std::string::size_type dot_pos = name.rfind("."); + if(dot_pos != kwsys_std::string::npos) + { + return name.substr(0, dot_pos); + } + else + { + return name; + } +} + +bool SystemTools::FileIsFullPath(const char* in_name) +{ + kwsys_std::string name = in_name; +#if defined(_WIN32) + // On Windows, the name must be at least two characters long. + if(name.length() < 2) + { + return false; + } + if(name[1] == ':') + { + return true; + } + if(name[0] == '\\') + { + return true; + } +#else + // On UNIX, the name must be at least one character long. + if(name.length() < 1) + { + return false; + } +#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(name[0] == '/') + { + return true; + } + return false; +} + +void SystemTools::Glob(const char *directory, const char *regexp, + kwsys_std::vector<kwsys_std::string>& files) +{ + Directory d; + RegularExpression reg(regexp); + + if (d.Load(directory)) + { + size_t numf; + unsigned int i; + numf = d.GetNumberOfFiles(); + for (i = 0; i < numf; i++) + { + kwsys_std::string fname = d.GetFile(i); + if (reg.find(fname)) + { + files.push_back(fname); + } + } + } +} + + +void SystemTools::GlobDirs(const char *fullPath, + kwsys_std::vector<kwsys_std::string>& files) +{ + kwsys_std::string path = fullPath; + kwsys_std::string::size_type pos = path.find("/*"); + if(pos == kwsys_std::string::npos) + { + files.push_back(fullPath); + return; + } + kwsys_std::string startPath = path.substr(0, pos); + kwsys_std::string finishPath = path.substr(pos+2); + + Directory d; + if (d.Load(startPath.c_str())) + { + for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) + { + if((kwsys_std::string(d.GetFile(i)) != ".") + && (kwsys_std::string(d.GetFile(i)) != "..")) + { + kwsys_std::string fname = startPath; + fname +="/"; + fname += d.GetFile(i); + if(SystemTools::FileIsDirectory(fname.c_str())) + { + fname += finishPath; + SystemTools::GlobDirs(fname.c_str(), files); + } + } + } + } +} + +bool SystemTools::GetShortPath(const char* path, kwsys_std::string& shortPath) +{ +#if defined(WIN32) && !defined(__CYGWIN__) + const int size = int(strlen(path)) +1; // size of return + char *buffer = new char[size]; // create a buffer + char *tempPath = new char[size]; // create a buffer + int ret; + + // if the path passed in has quotes around it, first remove the quotes + if (path[0] == '"' && path[strlen(path)-1] == '"') + { + strcpy(tempPath,path+1); + tempPath[strlen(tempPath)-1] = '\0'; + } + else + { + strcpy(tempPath,path); + } + + buffer[0] = 0; + ret = GetShortPathName(tempPath, buffer, size); + + if(buffer[0] == 0 || ret > size) + { + delete [] buffer; + delete [] tempPath; + return false; + } + else + { + shortPath = buffer; + delete [] buffer; + delete [] tempPath; + return true; + } +#else + shortPath = path; + return true; +#endif +} + +bool SystemTools::SimpleGlob(const kwsys_std::string& glob, + kwsys_std::vector<kwsys_std::string>& files, + int type /* = 0 */) +{ + files.clear(); + if ( glob[glob.size()-1] != '*' ) + { + return false; + } + kwsys_std::string path = SystemTools::GetFilenamePath(glob); + kwsys_std::string ppath = SystemTools::GetFilenameName(glob); + ppath = ppath.substr(0, ppath.size()-1); + if ( path.size() == 0 ) + { + path = "/"; + } + + bool res = false; + Directory d; + if (d.Load(path.c_str())) + { + for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) + { + if((kwsys_std::string(d.GetFile(i)) != ".") + && (kwsys_std::string(d.GetFile(i)) != "..")) + { + kwsys_std::string fname = path; + if ( path[path.size()-1] != '/' ) + { + fname +="/"; + } + fname += d.GetFile(i); + kwsys_std::string sfname = d.GetFile(i); + if ( type > 0 && SystemTools::FileIsDirectory(fname.c_str()) ) + { + continue; + } + if ( type < 0 && !SystemTools::FileIsDirectory(fname.c_str()) ) + { + continue; + } + if ( sfname.size() >= ppath.size() && + sfname.substr(0, ppath.size()) == + ppath ) + { + files.push_back(fname); + res = true; + } + } + } + } + return res; +} + + +void SystemTools::SplitProgramFromArgs(const char* path, + kwsys_std::string& program, kwsys_std::string& args) +{ + if(SystemTools::FileExists(path)) + { + program = path; + args = ""; + return; + } + kwsys_std::vector<kwsys_std::string> e; + kwsys_std::string findProg = SystemTools::FindProgram(path, e); + if(findProg.size()) + { + program = findProg; + args = ""; + return; + } + kwsys_std::string dir = path; + kwsys_std::string::size_type spacePos = dir.rfind(' '); + if(spacePos == kwsys_std::string::npos) + { + program = ""; + args = ""; + return; + } + while(spacePos != kwsys_std::string::npos) + { + kwsys_std::string tryProg = dir.substr(0, spacePos); + if(SystemTools::FileExists(tryProg.c_str())) + { + program = tryProg; + args = dir.substr(spacePos, dir.size()-spacePos); + return; + } + findProg = SystemTools::FindProgram(tryProg.c_str(), e); + if(findProg.size()) + { + program = findProg; + args = dir.substr(spacePos, dir.size()-spacePos); + return; + } + spacePos = dir.rfind(' ', spacePos--); + } + program = ""; + args = ""; +} + +kwsys_std::string SystemTools::GetCurrentDateTime(const char* format) +{ + char buf[1024]; + time_t t; + time(&t); + strftime(buf, sizeof(buf), format, localtime(&t)); + return buf; +} + +kwsys_std::string SystemTools::MakeCindentifier(const char* s) +{ + kwsys_std::string str(s); + if (str.find_first_of("0123456789") == 0) + { + str = "_" + str; + } + + kwsys_std::string permited_chars("_" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"); + kwsys_std::string::size_type pos = 0; + while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_std::string::npos) + { + str[pos] = '_'; + } + return str; +} + +// Due to a buggy stream library on the HP and another on Mac OSX, we +// need this very carefully written version of getline. Returns true +// if any data were read before the end-of-file was reached. +bool SystemTools::GetLineFromStream(kwsys_std::istream& is, kwsys_std::string& line) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + line = ""; + bool haveData = false; + + // If no characters are read from the stream, the end of file has + // been reached. + while((is.getline(buffer, bufferSize), is.gcount() > 0)) + { + haveData = true; + line.append(buffer); + + // If newline character was read, the gcount includes the + // character, but the buffer does not. The end of line has been + // reached. + if(strlen(buffer) < static_cast<size_t>(is.gcount())) + { + break; + } + + // The fail bit may be set. Clear it. + is.clear(is.rdstate() & ~kwsys_std::ios::failbit); + } + return haveData; +} + +#if defined(_MSC_VER) && defined(_DEBUG) +# include <crtdbg.h> +# include <stdio.h> +# include <stdlib.h> +static int SystemToolsDebugReport(int, char* message, int*) +{ + fprintf(stderr, message); + exit(1); + return 0; +} +void SystemTools::EnableMSVCDebugHook() +{ + if(getenv("DART_TEST_FROM_DART")) + { + _CrtSetReportHook(SystemToolsDebugReport); + } +} +#else +void SystemTools::EnableMSVCDebugHook() +{ +} +#endif + +} // namespace KWSYS_NAMESPACE |