Commits

Anonymous committed 7537d99

BUG: Fix bug#5590.
When converting a relative path between two full paths on different
windows drive letters do not create a ../../d:/foo/bar path and just
return the full path to the destination.

  • Participants
  • Parent commits 6c5fb0d
  • Branches ITK-3-4

Comments (0)

Files changed (1)

GCC_XML/KWSys/SystemTools.cxx

+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    $RCSfile$
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "kwsysPrivate.h"
+#include KWSYS_HEADER(SystemTools.hxx)
+#include KWSYS_HEADER(Directory.hxx)
+
+#include KWSYS_HEADER(ios/iostream)
+#include KWSYS_HEADER(ios/fstream)
+#include KWSYS_HEADER(ios/sstream)
+
+// Work-around CMake dependency scanning limitation.  This must
+// duplicate the above list of headers.
+#if 0
+# include "SystemTools.hxx.in"
+# include "Directory.hxx.in"
+# include "kwsys_ios_iostream.h.in"
+# include "kwsys_ios_fstream.h.in"
+# include "kwsys_ios_sstream.h.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 <sys/stat.h>
+#include <time.h>
+
+// support for realpath call
+#ifndef _WIN32
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <termios.h>
+#include <signal.h>    /* sigprocmask */
+#endif
+
+// Windows API.  Some parts used even on cygwin.
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
+// getpwnam doesn't exist on Windows and Cray Xt3/Catamount
+// same for TIOCGWINSZ
+#if defined(_WIN32) || defined (__LIBCATAMOUNT__)
+# undef HAVE_GETPWNAM
+# undef HAVE_TTY_INFO
+#else
+# define HAVE_GETPWNAM 1
+# define HAVE_TTY_INFO 1
+#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 <io.h>
+#include <direct.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, NULL, true);
+  const char *resolved = normalized.Path();
+  if (resolved != NULL)   // NULL == No such file. 
+    {
+    if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen) 
+      {
+      return resolved_path;
+      }
+    }
+  return NULL;   // something went wrong.
+}
+#endif
+
+#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__)) 
+inline int Mkdir(const char* dir)
+{
+  return _mkdir(dir);
+}
+inline int Rmdir(const char* dir)
+{
+  return _rmdir(dir);
+}
+inline const char* Getcwd(char* buf, unsigned int len)
+{
+  const char* ret = _getcwd(buf, len);
+  if(!ret)
+    {
+    fprintf(stderr, "No current working directory.\n");
+    abort();
+    }
+  // make sure the drive letter is capital
+  if(strlen(buf) > 1 && buf[1] == ':')
+    {
+    buf[0] = toupper(buf[0]);
+    }
+  return ret;
+}
+inline int Chdir(const char* dir)
+{
+  #if defined(__BORLANDC__)
+  return chdir(dir);
+  #else
+  return _chdir(dir);
+  #endif
+}
+inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
+{
+  char *ptemp;
+  char fullpath[MAX_PATH];
+  if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) )
+    {
+    resolved_path = fullpath;
+    KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
+    }
+}
+#else
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+inline int Mkdir(const char* dir)
+{
+  return mkdir(dir, 00777);
+}
+inline int Rmdir(const char* dir)
+{
+  return rmdir(dir);
+}
+inline const char* Getcwd(char* buf, unsigned int len)
+{
+  const char* ret = getcwd(buf, len);
+  if(!ret)
+    {
+    fprintf(stderr, "No current working directory\n");
+    abort();
+    }
+  return ret;
+}
+
+inline int Chdir(const char* dir)
+{
+  return chdir(dir);
+}
+inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
+{
+  char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
+
+  realpath(path, resolved_name);
+  resolved_path = resolved_name;
+}
+#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
+
+/* 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
+{
+
+class SystemToolsTranslationMap : 
+    public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
+{
+};
+
+
+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 static_cast<double>(t.tv_sec) + t.tv_usec*0.000001;
+#else /* !GETTIMEOFDAY_NO_TZ */
+  if (gettimeofday(&t, static_cast<struct timezone *>(NULL)) == 0)
+    return static_cast<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 static_cast<double>(t.time) +
+    static_cast<double>(t.millitm) * static_cast<double>(0.001);
+#else /* !HAVE_FTIME */
+  time_t secs;
+  time(&secs);
+  return static_cast<double>(secs);
+#endif /* !HAVE_FTIME */
+  }
+}
+
+// adds the elements of the env variable path to the arg passed in
+void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  const char* pathSep = ";";
+#else
+  const char* pathSep = ":";
+#endif
+  if(!env)
+    {
+    env = "PATH";
+    }
+  const char* cpathEnv = SystemTools::GetEnv(env);
+  if ( !cpathEnv )
+    {
+    return;
+    }
+
+  kwsys_stl::string pathEnv = cpathEnv;
+
+  // A hack to make the below algorithm work.
+  if(pathEnv[pathEnv.length()-1] != ':')
+    {
+    pathEnv += pathSep;
+    }
+  kwsys_stl::string::size_type start =0;
+  bool done = false;
+  while(!done)
+    {
+    kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
+    if(endpos != kwsys_stl::string::npos)
+      {
+      kwsys_stl::string convertedPath;
+      Realpath(pathEnv.substr(start, endpos-start).c_str(), convertedPath);
+      path.push_back(convertedPath);
+      start = endpos+1;
+      }
+    else
+      {
+      done = true;
+      }
+    }
+  for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
+      i != path.end(); ++i)
+    {
+    SystemTools::ConvertToUnixSlashes(*i);
+    }
+}
+
+const char* SystemTools::GetEnv(const char* key)
+{
+  return getenv(key);
+}
+
+bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
+{
+  const char* v = getenv(key);
+  if(v)
+    {
+    result = v;
+    return true;
+    }
+  else
+    {
+    return false;
+    }
+}
+
+const char* SystemTools::GetExecutableExtension()
+{
+#if defined(_WIN32) || defined(__CYGWIN__)
+  return ".exe";
+#else
+  return "";
+#endif  
+}
+
+
+bool SystemTools::MakeDirectory(const char* path)
+{
+  if(!path)
+    {
+    return false;
+    }
+  if(SystemTools::FileExists(path))
+    {
+    return true;
+    }
+  kwsys_stl::string dir = path;
+  if(dir.size() == 0)
+    {
+    return false;
+    }
+  SystemTools::ConvertToUnixSlashes(dir);
+
+  kwsys_stl::string::size_type pos = dir.find(':');
+  if(pos == kwsys_stl::string::npos)
+    {
+    pos = 0;
+    }
+  kwsys_stl::string topdir;
+  while((pos = dir.find('/', pos)) != kwsys_stl::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_stl::string& source,
+                                   const char* replace,
+                                   const char* 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
+  size_t replaceSize = strlen(replace);
+  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);
+}
+
+// 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_stl::string &value)
+{
+
+  kwsys_stl::string primary = key;
+  kwsys_stl::string second;
+  kwsys_stl::string valuename;
+ 
+  size_t start = primary.find("\\");
+  if (start == kwsys_stl::string::npos)
+    {
+    return false;
+    }
+
+  size_t valuenamepos = primary.find(";");
+  if (valuenamepos != kwsys_stl::string::npos)
+    {
+    valuename = primary.substr(valuenamepos+1);
+    }
+
+  second = primary.substr(start+1, valuenamepos-start-1);
+  primary = primary.substr(0, start);
+  
+  HKEY primaryKey = HKEY_CURRENT_USER;
+  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;
+        RegCloseKey(hKey);
+        return true;
+        }
+      }
+    }
+  return false;
+}
+#else
+bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::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_stl::string primary = key;
+  kwsys_stl::string second;
+  kwsys_stl::string valuename;
+ 
+  size_t start = primary.find("\\");
+  if (start == kwsys_stl::string::npos)
+    {
+    return false;
+    }
+
+  size_t valuenamepos = primary.find(";");
+  if (valuenamepos != kwsys_stl::string::npos)
+    {
+    valuename = primary.substr(valuenamepos+1);
+    }
+
+  second = primary.substr(start+1, valuenamepos-start-1);
+  primary = primary.substr(0, start);
+  
+  HKEY primaryKey = HKEY_CURRENT_USER;
+  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_stl::string primary = key;
+  kwsys_stl::string second;
+  kwsys_stl::string valuename;
+ 
+  size_t start = primary.find("\\");
+  if (start == kwsys_stl::string::npos)
+    {
+    return false;
+    }
+
+  size_t valuenamepos = primary.find(";");
+  if (valuenamepos != kwsys_stl::string::npos)
+    {
+    valuename = primary.substr(valuenamepos+1);
+    }
+
+  second = primary.substr(start+1, valuenamepos-start-1);
+  primary = primary.substr(0, start);
+  
+  HKEY primaryKey = HKEY_CURRENT_USER;
+  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)
+      {
+      RegCloseKey(hKey);
+      return true;
+      }
+    }
+  return false;
+}
+#else
+bool SystemTools::DeleteRegistryValue(const char *)
+{
+  return false;
+}
+#endif
+
+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.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
+           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)
+{
+#ifdef _MSC_VER
+# define access _access
+#endif
+#ifndef R_OK
+# define R_OK 04
+#endif
+  if ( access(filename, R_OK) != 0 )
+    {
+    return false;
+    }
+  else
+    {
+    return true;
+    }
+}
+
+
+bool SystemTools::FileTimeCompare(const char* f1, const char* 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, &s1) != 0)
+    {
+    return false;
+    }
+  struct stat s2;
+  if(stat(f2, &s2) != 0)
+    {
+    return false;
+    }
+# if KWSYS_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;
+    }
+# 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(!GetFileAttributesEx(f1, GetFileExInfoStandard, &f1d))
+    {
+    return false;
+    }
+  if(!GetFileAttributesEx(f2, 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)
+kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s)
+{
+  kwsys_stl::string n;
+  if(s.size() == 0)
+    {
+    return n;
+    }
+  n.resize(s.size());
+  n[0] = static_cast<kwsys_stl::string::value_type>(toupper(s[0]));
+  for (size_t i = 1; i < s.size(); i++)
+    {
+    n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
+    }
+  return n;
+}
+
+// Return capitalized words
+kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s)
+{
+  kwsys_stl::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<kwsys_stl::string::value_type>(toupper(s[i]));
+      }
+    }
+  return n;
+}
+
+// Return uncapitalized words
+kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s)
+{
+  kwsys_stl::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<kwsys_stl::string::value_type>(tolower(s[i]));
+      }
+    }
+  return n;
+}
+
+// only works for words with at least two letters
+kwsys_stl::string SystemTools::AddSpaceBetweenCapitalizedWords(
+  const kwsys_stl::string& s)
+{
+  kwsys_stl::string n;
+  if (s.size())
+    {
+    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 0;
+    }
+  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 0;
+    }
+  strcpy(newstr, str1);
+  strcat(newstr + len1, str2);
+  strcat(newstr + len1 + len2, str3);
+  return newstr;
+}
+
+// Return a lower case string 
+kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s)
+{
+  kwsys_stl::string n;
+  n.resize(s.size());
+  for (size_t i = 0; i < s.size(); i++)
+    {
+    n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
+    }
+  return n;
+}
+
+// Return a lower case string 
+kwsys_stl::string SystemTools::UpperCase(const kwsys_stl::string& s)
+{
+  kwsys_stl::string n;
+  n.resize(s.size());
+  for (size_t i = 0; i < s.size(); i++)
+    {
+    n[i] = static_cast<kwsys_stl::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 NULL;
+    }
+  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 0;
+    }
+  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 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 a pointer to the last occurence of str2 in str1
+const char* SystemTools::FindLastString(const char* str1, const char* str2)
+{
+  if (!str1 || !str2)
+    {
+    return NULL;
+    }
+  
+  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 NULL;
+}
+
+// Duplicate string
+char* SystemTools::DuplicateString(const char* str)
+{
+  if (str)
+    {
+    char *newstr = new char [strlen(str) + 1];
+    return strcpy(newstr, str);
+    }
+  return NULL;
+}
+
+// Return a cropped string 
+kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s, 
+                                          size_t max_len)
+{
+  if (!s.size() || max_len == 0 || max_len >= s.size())
+    {
+    return s;
+    }
+
+  kwsys_stl::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), kwsys_stl::string::npos);
+
+  if (max_len > 2)
+    {
+    n[middle] = '.';
+    if (max_len > 3)
+      {
+      n[middle - 1] = '.';
+      if (max_len > 4)
+        {
+        n[middle + 1] = '.';
+        }
+      }
+    }
+
+  return n;
+}
+
+//----------------------------------------------------------------------------
+kwsys_stl::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
+{
+  kwsys_stl::string path = p;
+  kwsys_stl::vector<kwsys::String> paths;
+  if(isPath && path[0] == '/')
+    {
+    path.erase(path.begin());
+    paths.push_back("/"); 
+    }
+  kwsys_stl::string::size_type pos1 = 0;
+  kwsys_stl::string::size_type pos2 = path.find(sep, pos1+1);
+  while(pos2 != kwsys_stl::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);
+}
+
+kwsys_stl::string SystemTools::EscapeChars(
+  const char *str, 
+  const char *chars_to_escape, 
+  char escape_char)
+{
+  kwsys_stl::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;
+}
+
+// convert windows slashes to unix slashes 
+void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
+{
+  const char* pathCString = path.c_str();
+  bool hasDoubleSlash = false;
+
+  const char* pos0 = pathCString;
+  const char* pos1 = pathCString+1;
+  for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos )
+    {
+    // make sure we don't convert an escaped space to a unix slash
+    if ( *pos0 == '\\' && *pos1 != ' ' )
+      {
+      path[pos] = '/';
+      }
+
+    // Also, reuse the loop to check for slash followed by another slash
+    if (*pos1 == '/' && *(pos1+1) == '/' && !hasDoubleSlash)
+      {
+#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 ++;
+    pos1 ++;
+    }
+
+  if ( hasDoubleSlash )
+    {
+    SystemTools::ReplaceString(path, "//", "/");
+    }
+  
+  // remove any trailing slash
+  if(!path.empty())
+    {
+    // if there is a tilda ~ then replace it with HOME
+    pathCString = path.c_str();
+    if(pathCString[0] == '~' && (pathCString[1] == '/' || pathCString[1] == '\0'))
+      {
+      const char* homeEnv = SystemTools::GetEnv("HOME");
+      if (homeEnv)
+        {
+        path.replace(0,1,homeEnv);
+        }
+      }
+#ifdef HAVE_GETPWNAM
+    else if(pathCString[0] == '~')
+      {
+      kwsys_stl::string::size_type idx = path.find_first_of("/\0");
+      kwsys_stl::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();
+    if(path.size() > 1 && *(pathCString+(path.size()-1)) == '/')
+      {
+      // if it is c:/ then do not remove the trailing slash
+      if(!((path.size() == 3 && pathCString[1] == ':')))
+        {
+        path = path.substr(0, path.size()-1);
+        }
+      }
+    }
+}
+
+// change // to /, and escape any spaces in the path
+kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
+{
+  kwsys_stl::string ret = path;
+  
+  // remove // except at the beginning might be a cygwin drive
+  kwsys_stl::string::size_type pos=0;
+  while((pos = ret.find("//", pos)) != kwsys_stl::string::npos)
+    {
+    ret.erase(pos, 1);
+    }
+  // escape spaces and () in the path
+  if(ret.find_first_of(" ") != kwsys_stl::string::npos)
+    {
+    kwsys_stl::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_stl::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_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path)
+{  
+  kwsys_stl::string ret;
+  // make it big enough for all of path and double quotes
+  ret.reserve(strlen(path)+3);
+  // put path into the string
+  ret.insert(0,path);
+  kwsys_stl::string::size_type pos = 0;
+  // first convert all of the slashes
+  while((pos = ret.find('/', pos)) != kwsys_stl::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_stl::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_stl::string::npos
+     && ret[0] != '\"')
+    {
+    ret.insert(static_cast<kwsys_stl::string::size_type>(0),
+               static_cast<kwsys_stl::string::size_type>(1), '\"');
+    ret.append(1, '\"');
+    }
+  return ret;
+}
+
+bool SystemTools::CopyFileIfDifferent(const char* source,
+                                      const char* destination)
+{
+  // special check for a destination that is a directory
+  // FilesDiffer does not handle file to directory compare
+  if(SystemTools::FileIsDirectory(destination))
+    {
+    kwsys_stl::string new_destination = destination;
+    SystemTools::ConvertToUnixSlashes(new_destination);
+    new_destination += '/';
+    kwsys_stl::string source_name = source;
+    new_destination += SystemTools::GetFilenameName(source_name);
+    if(SystemTools::FilesDiffer(source, new_destination.c_str()))
+      {
+      return SystemTools::CopyFileAlways(source, destination);
+      }
+    else
+      {
+      // the files are the same so the copy is done return
+      // true
+      return true;
+      }
+    }
+  // 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 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_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
+                                         kwsys_ios::ios::in));
+  kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
+                                                   kwsys_ios::ios::in));
+#else
+  kwsys_ios::ifstream finSource(source);
+  kwsys_ios::ifstream finDestination(destination);
+#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];
+  long nleft = statSource.st_size;
+  while(nleft > 0)
+    {
+    // Read a block from each file.
+    long nnext = (nleft > KWSYS_ST_BUFFER)? KWSYS_ST_BUFFER : nleft;
+    finSource.read(source_buf, nnext);
+    finDestination.read(dest_buf, nnext);
+
+    // If either failed to read assume they are different.
+    if(static_cast<long>(finSource.gcount()) != nnext ||
+       static_cast<long>(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), nnext) != 0)
+      {
+      return true;
+      }
+
+    // Update the byte count remaining.
+    nleft -= nnext;
+    }
+
+  // No differences found.
+  return false;
+}
+
+
+/**
+ * Copy a file named by "source" to the file named by "destination".
+ */
+bool SystemTools::CopyFileAlways(const char* source, const char* destination)
+{
+  // If files are the same do not copy
+  if ( SystemTools::SameFile(source, destination) )
+    {
+    return true;
+    }
+  mode_t perm = 0;
+  bool perms = SystemTools::GetPermissions(source, perm);
+
+  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_stl::string new_destination;
+  if(SystemTools::FileExists(destination) &&
+     SystemTools::FileIsDirectory(destination))
+    {
+    new_destination = destination;
+    SystemTools::ConvertToUnixSlashes(new_destination);
+    new_destination += '/';
+    kwsys_stl::string source_name = source;
+    new_destination += SystemTools::GetFilenameName(source_name);
+    destination = new_destination.c_str();
+    }
+
+  // Create destination directory
+
+  kwsys_stl::string destination_dir = destination;
+  destination_dir = SystemTools::GetFilenamePath(destination_dir);
+  SystemTools::MakeDirectory(destination_dir.c_str());
+
+  // Open files
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+  kwsys_ios::ifstream fin(source, 
+                    kwsys_ios::ios::binary | kwsys_ios::ios::in);
+#else
+  kwsys_ios::ifstream fin(source);
+#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) || defined(__CYGWIN__)
+  kwsys_ios::ofstream fout(destination, 
+                     kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc);
+#else
+  kwsys_ios::ofstream fout(destination, 
+                     kwsys_ios::ios::out | kwsys_ios::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;
+    }
+  if ( perms )
+    {
+    if ( !SystemTools::SetPermissions(destination, perm) )
+      {
+      return false;
+      }
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool SystemTools::CopyAFile(const char* source, const char* 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 char* source, const char* destination,
+                                 bool always)
+{
+  Directory dir;
+  dir.Load(source);
+  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)),".."))
+      {
+      kwsys_stl::string fullPath = source;
+      fullPath += "/";
+      fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
+      if(SystemTools::FileIsDirectory(fullPath.c_str()))
+        {
+        kwsys_stl::string fullDestPath = destination;
+        fullDestPath += "/";
+        fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
+        if (!SystemTools::CopyADirectory(fullPath.c_str(),
+                                         fullDestPath.c_str(),
+                                         always))
+          {
+          return false;
+          }
+        }
+      else
+        {
+        if(!SystemTools::CopyAFile(fullPath.c_str(), destination, always))
+          {
+          return false;
+          }
+        }
+      }
+    }
+
+  return true;
+}
+
+
+// return size of file; also returns zero if no file exists
+unsigned long SystemTools::FileLength(const char* filename)
+{
+  struct stat fs;
+  if (stat(filename, &fs) != 0) 
+    {
+      return 0;
+    }
+  else
+    {
+      return static_cast<unsigned long>(fs.st_size);
+    }
+}
+
+int SystemTools::Strucmp(const char *s1, const char *s2)
+{
+  // lifted from Graphvis http://www.graphviz.org
+  while ((*s1 != '\0')
+         && (tolower(*s1) == tolower(*s2)))
+    {
+      s1++;
+      s2++;
+    }
+
+  return tolower(*s1) - tolower(*s2);
+}
+
+// return file's modified time
+long int SystemTools::ModifiedTime(const char* filename)
+{
+  struct stat fs;
+  if (stat(filename, &fs) != 0)
+    {
+    return 0;
+    }
+  else
+    {
+    return static_cast<long int>(fs.st_mtime);
+    }
+}
+
+// return file's creation time
+long int SystemTools::CreationTime(const char* filename)
+{
+  struct stat fs;
+  if (stat(filename, &fs) != 0)
+    {
+    return 0;
+    }
+  else
+    {
+    return fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0;
+    }
+}
+
+bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt)
+{
+  if (!str || !tmt || strlen(str) > 11)
+    {
+    return false;
+    }
+
+  struct tm tmt2;
+
+  // __DATE__
+  // The compilation date of the current source file. The date is a string
+  // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
+  // dates generated by the library function asctime declared in TIME.H.
+
+  // index:   012345678901
+  // format:  Mmm dd yyyy
+  // example: Dec 19 2003
+
+  static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+  char buffer[12];
+  strcpy(buffer, str);
+
+  buffer[3] = 0;
+  char *ptr = strstr(month_names, buffer);
+  if (!ptr)
+    {
+    return false;
+    }
+
+  int month = (ptr - month_names) / 3;
+  int day = atoi(buffer + 4);
+  int year = atoi(buffer + 7);
+
+  tmt2.tm_isdst = -1;
+  tmt2.tm_hour  = 0;
+  tmt2.tm_min   = 0;
+  tmt2.tm_sec   = 0;
+  tmt2.tm_wday  = 0;
+  tmt2.tm_yday  = 0;
+  tmt2.tm_mday  = day;
+  tmt2.tm_mon   = month;
+  tmt2.tm_year  = year - 1900;
+
+  *tmt = mktime(&tmt2);
+  return true;
+}
+
+bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt)
+{
+  if (!str || !tmt || strlen(str) > 26)
+    {
+    return false;
+    }
+
+  struct tm tmt2;
+
+  // __TIMESTAMP__
+  // The date and time of the last modification of the current source file,
+  // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
+  /// where Ddd is the abbreviated day of the week and Date is an integer
+  // from 1 to 31.
+
+  // index:   0123456789
+  //                    0123456789
+  //                              0123456789
+  // format:  Ddd Mmm Date hh:mm:ss yyyy
+  // example: Fri Dec 19 14:34:58 2003
+
+  static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+  char buffer[27];
+  strcpy(buffer, str);
+
+  buffer[7] = 0;
+  char *ptr = strstr(month_names, buffer + 4);
+  if (!ptr)
+    {
+    return false;
+    }
+
+  int month = (ptr - month_names) / 3;
+  int day = atoi(buffer + 8);
+  int hour = atoi(buffer + 11);
+  int min = atoi(buffer + 14);
+  int sec = atoi(buffer + 17);
+  int year = atoi(buffer + 20);
+
+  tmt2.tm_isdst = -1;
+  tmt2.tm_hour  = hour;
+  tmt2.tm_min   = min;
+  tmt2.tm_sec   = sec;
+  tmt2.tm_wday  = 0;
+  tmt2.tm_yday  = 0;
+  tmt2.tm_mday  = day;
+  tmt2.tm_mon   = month;
+  tmt2.tm_year  = year - 1900;
+
+  *tmt = mktime(&tmt2);
+  return true;
+}
+
+kwsys_stl::string SystemTools::GetLastSystemError()
+{
+  int e = errno;
+  return strerror(e);
+}
+
+bool SystemTools::RemoveFile(const char* source)
+{
+#ifdef _WIN32
+  mode_t mode;
+  if ( !SystemTools::GetPermissions(source, mode) )
+    {
+    return false;
+    }
+  /* Win32 unlink is stupid --- it fails if the file is read-only  */
+  SystemTools::SetPermissions(source, S_IWRITE);
+#endif
+  bool res = unlink(source) != 0 ? false : true;
+#ifdef _WIN32
+  if ( !res )
+    {
+    SystemTools::SetPermissions(source, mode);
+    }
+#endif
+  return res;
+}
+
+bool SystemTools::RemoveADirectory(const char* source)
+{
+  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)),".."))
+      {
+      kwsys_stl::string fullPath = source;
+      fullPath += "/";
+      fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
+      if(SystemTools::FileIsDirectory(fullPath.c_str()) &&
+        !SystemTools::FileIsSymlink(fullPath.c_str()))
+        {
+        if (!SystemTools::RemoveADirectory(fullPath.c_str()))
+          {
+          return false;
+          }
+        }
+      else
+        {
+        if(!SystemTools::RemoveFile(fullPath.c_str()))
+          {
+          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.
+ */
+kwsys_stl::string SystemTools
+::FindName(const char* name,
+           const kwsys_stl::vector<kwsys_stl::string>& userPaths,
+           bool no_system_path)
+{
+  // Add the system search path to our path first
+  kwsys_stl::vector<kwsys_stl::string> path;
+  if (!no_system_path) 
+    {
+    SystemTools::GetPath(path, "CMAKE_FILE_PATH");
+    SystemTools::GetPath(path);
+    }
+  // now add the additional paths
+  for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
+        i != userPaths.end(); ++i)
+    {
+    path.push_back(*i);
+    }
+  // now look for the file
+  kwsys_stl::string tryPath;
+  for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
+      p != path.end(); ++p)
+    {
+    tryPath = *p;
+    tryPath += "/";
+    tryPath += name;
+    if(SystemTools::FileExists(tryPath.c_str()))
+      {
+      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.
+ */
+kwsys_stl::string SystemTools
+::FindFile(const char* name,
+           const kwsys_stl::vector<kwsys_stl::string>& userPaths,
+           bool no_system_path)
+{
+  kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
+  if(tryPath != "" && !SystemTools::FileIsDirectory(tryPath.c_str()))
+    {
+    return SystemTools::CollapseFullPath(tryPath.c_str());
+    }
+  // 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.
+ */
+kwsys_stl::string SystemTools
+::FindDirectory(const char* name,
+                const kwsys_stl::vector<kwsys_stl::string>& userPaths,
+                bool no_system_path)
+{
+  kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
+  if(tryPath != "" && 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_stl::string SystemTools::FindProgram(
+  const char* nameIn,
+  const kwsys_stl::vector<kwsys_stl::string>& userPaths,
+  bool no_system_path)
+{
+  if(!nameIn || !*nameIn)
+    {
+    return "";
+    }
+  kwsys_stl::string name = nameIn;
+  kwsys_stl::vector<kwsys_stl::string> extensions;
+#if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+  bool hasExtension = false;
+  // check to see if the name already has a .xxx at
+  // the end of it
+  if(name.size() > 3 && name[name.size()-4] == '.')
+    {
+    hasExtension = true;
+    }
+  // on windows try .com then .exe
+  if(!hasExtension)
+    {
+    extensions.push_back(".com");
+    extensions.push_back(".exe");
+    }