Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / kwsys / SystemTools.cxx
blobcd99225c6dac3cdf88b9d9baa87a121788fddc4f
1 /*=========================================================================
3 Program: KWSys - Kitware System Library
4 Module: $RCSfile: SystemTools.cxx,v $
6 Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notices for more information.
13 =========================================================================*/
14 #include "kwsysPrivate.h"
15 #include KWSYS_HEADER(RegularExpression.hxx)
16 #include KWSYS_HEADER(SystemTools.hxx)
17 #include KWSYS_HEADER(Directory.hxx)
19 #include KWSYS_HEADER(ios/iostream)
20 #include KWSYS_HEADER(ios/fstream)
21 #include KWSYS_HEADER(ios/sstream)
23 // Work-around CMake dependency scanning limitation. This must
24 // duplicate the above list of headers.
25 #if 0
26 # include "SystemTools.hxx.in"
27 # include "Directory.hxx.in"
28 # include "kwsys_ios_iostream.h.in"
29 # include "kwsys_ios_fstream.h.in"
30 # include "kwsys_ios_sstream.h.in"
31 #endif
33 #ifdef _MSC_VER
34 # pragma warning (disable: 4786)
35 #endif
37 #if defined(__sgi) && !defined(__GNUC__)
38 # pragma set woff 1375 /* base class destructor not virtual */
39 #endif
41 #include <ctype.h>
42 #include <errno.h>
43 #ifdef __QNX__
44 # include <malloc.h> /* for malloc/free on QNX */
45 #endif
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <sys/stat.h>
50 #include <time.h>
52 // support for realpath call
53 #ifndef _WIN32
54 #include <utime.h>
55 #include <limits.h>
56 #include <sys/param.h>
57 #include <sys/wait.h>
58 #include <sys/ioctl.h>
59 #include <unistd.h>
60 #include <pwd.h>
61 #include <termios.h>
62 #include <signal.h> /* sigprocmask */
63 #endif
65 // Windows API. Some parts used even on cygwin.
66 #if defined(_WIN32)
67 # include <windows.h>
68 #endif
70 // getpwnam doesn't exist on Windows and Cray Xt3/Catamount
71 // same for TIOCGWINSZ
72 #if defined(_WIN32) || defined (__LIBCATAMOUNT__)
73 # undef HAVE_GETPWNAM
74 # undef HAVE_TTY_INFO
75 #else
76 # define HAVE_GETPWNAM 1
77 # define HAVE_TTY_INFO 1
78 #endif
80 #define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)"
81 #define VTK_URL_REGEX "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/(.+)?"
83 #ifdef _MSC_VER
84 #include <sys/utime.h>
85 #else
86 #include <utime.h>
87 #endif
90 // This is a hack to prevent warnings about these functions being
91 // declared but not referenced.
92 #if defined(__sgi) && !defined(__GNUC__)
93 # include <sys/termios.h>
94 namespace KWSYS_NAMESPACE
96 class SystemToolsHack
98 public:
99 enum
101 Ref1 = sizeof(cfgetospeed(0)),
102 Ref2 = sizeof(cfgetispeed(0)),
103 Ref3 = sizeof(tcgetattr(0, 0)),
104 Ref4 = sizeof(tcsetattr(0, 0, 0)),
105 Ref5 = sizeof(cfsetospeed(0,0)),
106 Ref6 = sizeof(cfsetispeed(0,0))
110 #endif
112 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) ||defined(__BORLANDC__) || defined(__MINGW32__))
113 #include <io.h>
114 #include <direct.h>
115 #define _unlink unlink
116 #endif
118 /* The maximum length of a file name. */
119 #if defined(PATH_MAX)
120 # define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
121 #elif defined(MAXPATHLEN)
122 # define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
123 #else
124 # define KWSYS_SYSTEMTOOLS_MAXPATH 16384
125 #endif
126 #if defined(__WATCOMC__)
127 #include <direct.h>
128 #define _mkdir mkdir
129 #define _rmdir rmdir
130 #define _getcwd getcwd
131 #define _chdir chdir
132 #endif
134 #if defined(__HAIKU__)
135 #include <os/kernel/OS.h>
136 #include <os/storage/Path.h>
137 #endif
139 #if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
140 #include <be/kernel/OS.h>
141 #include <be/storage/Path.h>
143 // BeOS 5 doesn't have usleep(), but it has snooze(), which is identical.
144 static inline void usleep(unsigned int msec)
146 ::snooze(msec);
149 // BeOS 5 also doesn't have realpath(), but its C++ API offers something close.
150 static inline char *realpath(const char *path, char *resolved_path)
152 const size_t maxlen = KWSYS_SYSTEMTOOLS_MAXPATH;
153 snprintf(resolved_path, maxlen, "%s", path);
154 BPath normalized(resolved_path, NULL, true);
155 const char *resolved = normalized.Path();
156 if (resolved != NULL) // NULL == No such file.
158 if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen)
160 return resolved_path;
163 return NULL; // something went wrong.
165 #endif
167 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
168 inline int Mkdir(const char* dir)
170 return _mkdir(dir);
172 inline int Rmdir(const char* dir)
174 return _rmdir(dir);
176 inline const char* Getcwd(char* buf, unsigned int len)
178 const char* ret = _getcwd(buf, len);
179 if(!ret)
181 fprintf(stderr, "No current working directory.\n");
182 abort();
184 // make sure the drive letter is capital
185 if(strlen(buf) > 1 && buf[1] == ':')
187 buf[0] = toupper(buf[0]);
189 return ret;
191 inline int Chdir(const char* dir)
193 #if defined(__BORLANDC__)
194 return chdir(dir);
195 #else
196 return _chdir(dir);
197 #endif
199 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
201 char *ptemp;
202 char fullpath[MAX_PATH];
203 if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) )
205 resolved_path = fullpath;
206 KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
208 else
210 resolved_path = path;
213 #else
214 #include <sys/types.h>
215 #include <fcntl.h>
216 #include <unistd.h>
217 inline int Mkdir(const char* dir)
219 return mkdir(dir, 00777);
221 inline int Rmdir(const char* dir)
223 return rmdir(dir);
225 inline const char* Getcwd(char* buf, unsigned int len)
227 const char* ret = getcwd(buf, len);
228 if(!ret)
230 fprintf(stderr, "No current working directory\n");
231 abort();
233 return ret;
236 inline int Chdir(const char* dir)
238 return chdir(dir);
240 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
242 char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
244 char *ret = realpath(path, resolved_name);
245 if(ret)
247 resolved_path = ret;
249 else
251 // if path resolution fails, return what was passed in
252 resolved_path = path;
255 #endif
257 #if !defined(_WIN32) && defined(__COMO__)
258 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
259 extern "C"
261 extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
262 extern int pclose (FILE *__stream) __THROW;
263 extern char *realpath (__const char *__restrict __name,
264 char *__restrict __resolved) __THROW;
265 extern char *strdup (__const char *__s) __THROW;
266 extern int putenv (char *__string) __THROW;
268 #endif
270 /* Implement floattime() for various platforms */
271 // Taken from Python 2.1.3
273 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
274 # include <sys/timeb.h>
275 # define HAVE_FTIME
276 # if defined( __BORLANDC__)
277 # define FTIME ftime
278 # define TIMEB timeb
279 # else // Visual studio?
280 # define FTIME _ftime
281 # define TIMEB _timeb
282 # endif
283 #elif defined( __CYGWIN__ ) || defined( __linux__ )
284 # include <sys/time.h>
285 # include <time.h>
286 # define HAVE_GETTIMEOFDAY
287 #endif
289 namespace KWSYS_NAMESPACE
292 class SystemToolsTranslationMap :
293 public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
298 double
299 SystemTools::GetTime(void)
301 /* There are three ways to get the time:
302 (1) gettimeofday() -- resolution in microseconds
303 (2) ftime() -- resolution in milliseconds
304 (3) time() -- resolution in seconds
305 In all cases the return value is a float in seconds.
306 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
307 fail, so we fall back on ftime() or time().
308 Note: clock resolution does not imply clock accuracy! */
309 #ifdef HAVE_GETTIMEOFDAY
311 struct timeval t;
312 #ifdef GETTIMEOFDAY_NO_TZ
313 if (gettimeofday(&t) == 0)
314 #else /* !GETTIMEOFDAY_NO_TZ */
315 if (gettimeofday(&t, static_cast<struct timezone *>(NULL)) == 0)
316 #endif /* !GETTIMEOFDAY_NO_TZ */
317 return static_cast<double>(t.tv_sec) +
318 static_cast<double>(t.tv_usec)*0.000001;
320 #endif /* !HAVE_GETTIMEOFDAY */
322 #if defined(HAVE_FTIME)
323 struct TIMEB t;
324 ::FTIME(&t);
325 return static_cast<double>(t.time) +
326 static_cast<double>(t.millitm) * static_cast<double>(0.001);
327 #else /* !HAVE_FTIME */
328 time_t secs;
329 time(&secs);
330 return static_cast<double>(secs);
331 #endif /* !HAVE_FTIME */
335 // adds the elements of the env variable path to the arg passed in
336 void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
338 #if defined(_WIN32) && !defined(__CYGWIN__)
339 const char* pathSep = ";";
340 #else
341 const char* pathSep = ":";
342 #endif
343 if(!env)
345 env = "PATH";
347 const char* cpathEnv = SystemTools::GetEnv(env);
348 if ( !cpathEnv )
350 return;
353 kwsys_stl::string pathEnv = cpathEnv;
355 // A hack to make the below algorithm work.
356 if(pathEnv[pathEnv.length()-1] != ':')
358 pathEnv += pathSep;
360 kwsys_stl::string::size_type start =0;
361 bool done = false;
362 while(!done)
364 kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
365 if(endpos != kwsys_stl::string::npos)
367 kwsys_stl::string convertedPath;
368 Realpath(pathEnv.substr(start, endpos-start).c_str(), convertedPath);
369 path.push_back(convertedPath);
370 start = endpos+1;
372 else
374 done = true;
377 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
378 i != path.end(); ++i)
380 SystemTools::ConvertToUnixSlashes(*i);
384 const char* SystemTools::GetEnv(const char* key)
386 return getenv(key);
389 bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
391 const char* v = getenv(key);
392 if(v)
394 result = v;
395 return true;
397 else
399 return false;
403 const char* SystemTools::GetExecutableExtension()
405 #if defined(_WIN32) || defined(__CYGWIN__)
406 return ".exe";
407 #else
408 return "";
409 #endif
413 bool SystemTools::MakeDirectory(const char* path)
415 if(!path)
417 return false;
419 if(SystemTools::FileExists(path))
421 return true;
423 kwsys_stl::string dir = path;
424 if(dir.size() == 0)
426 return false;
428 SystemTools::ConvertToUnixSlashes(dir);
430 kwsys_stl::string::size_type pos = dir.find(':');
431 if(pos == kwsys_stl::string::npos)
433 pos = 0;
435 kwsys_stl::string topdir;
436 while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
438 topdir = dir.substr(0, pos);
439 Mkdir(topdir.c_str());
440 pos++;
442 if(dir[dir.size()-1] == '/')
444 topdir = dir.substr(0, dir.size());
446 else
448 topdir = dir;
450 if(Mkdir(topdir.c_str()) != 0)
452 // There is a bug in the Borland Run time library which makes MKDIR
453 // return EACCES when it should return EEXISTS
454 // if it is some other error besides directory exists
455 // then return false
456 if( (errno != EEXIST)
457 #ifdef __BORLANDC__
458 && (errno != EACCES)
459 #endif
462 return false;
465 return true;
469 // replace replace with with as many times as it shows up in source.
470 // write the result into source.
471 void SystemTools::ReplaceString(kwsys_stl::string& source,
472 const char* replace,
473 const char* with)
475 const char *src = source.c_str();
476 char *searchPos = const_cast<char *>(strstr(src,replace));
478 // get out quick if string is not found
479 if (!searchPos)
481 return;
484 // perform replacements until done
485 size_t replaceSize = strlen(replace);
486 // do while hangs if replaceSize is 0
487 if(replaceSize == 0)
489 return;
491 char *orig = strdup(src);
492 char *currentPos = orig;
493 searchPos = searchPos - src + orig;
495 // initialize the result
496 source.erase(source.begin(),source.end());
499 *searchPos = '\0';
500 source += currentPos;
501 currentPos = searchPos + replaceSize;
502 // replace
503 source += with;
504 searchPos = strstr(currentPos,replace);
506 while (searchPos);
508 // copy any trailing text
509 source += currentPos;
510 free(orig);
513 #if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
514 # define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
515 # define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
516 #else
517 # define KWSYS_ST_KEY_WOW64_32KEY 0x0200
518 # define KWSYS_ST_KEY_WOW64_64KEY 0x0100
519 #endif
521 #if defined(_WIN32) && !defined(__CYGWIN__)
522 static DWORD SystemToolsMakeRegistryMode(DWORD mode,
523 SystemTools::KeyWOW64 view)
525 if(view == SystemTools::KeyWOW64_32)
527 return mode | KWSYS_ST_KEY_WOW64_32KEY;
529 else if(view == SystemTools::KeyWOW64_64)
531 return mode | KWSYS_ST_KEY_WOW64_64KEY;
533 return mode;
535 #endif
537 // Read a registry value.
538 // Example :
539 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
540 // => will return the data of the "default" value of the key
541 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
542 // => will return the data of the "Root" value of the key
544 #if defined(_WIN32) && !defined(__CYGWIN__)
545 bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
546 KeyWOW64 view)
548 bool valueset = false;
549 kwsys_stl::string primary = key;
550 kwsys_stl::string second;
551 kwsys_stl::string valuename;
553 size_t start = primary.find("\\");
554 if (start == kwsys_stl::string::npos)
556 return false;
559 size_t valuenamepos = primary.find(";");
560 if (valuenamepos != kwsys_stl::string::npos)
562 valuename = primary.substr(valuenamepos+1);
565 second = primary.substr(start+1, valuenamepos-start-1);
566 primary = primary.substr(0, start);
568 HKEY primaryKey = HKEY_CURRENT_USER;
569 if (primary == "HKEY_CURRENT_USER")
571 primaryKey = HKEY_CURRENT_USER;
573 if (primary == "HKEY_CURRENT_CONFIG")
575 primaryKey = HKEY_CURRENT_CONFIG;
577 if (primary == "HKEY_CLASSES_ROOT")
579 primaryKey = HKEY_CLASSES_ROOT;
581 if (primary == "HKEY_LOCAL_MACHINE")
583 primaryKey = HKEY_LOCAL_MACHINE;
585 if (primary == "HKEY_USERS")
587 primaryKey = HKEY_USERS;
590 HKEY hKey;
591 if(RegOpenKeyEx(primaryKey,
592 second.c_str(),
594 SystemToolsMakeRegistryMode(KEY_READ, view),
595 &hKey) != ERROR_SUCCESS)
597 return false;
599 else
601 DWORD dwType, dwSize;
602 dwSize = 1023;
603 char data[1024];
604 if(RegQueryValueEx(hKey,
605 (LPTSTR)valuename.c_str(),
606 NULL,
607 &dwType,
608 (BYTE *)data,
609 &dwSize) == ERROR_SUCCESS)
611 if (dwType == REG_SZ)
613 value = data;
614 valueset = true;
616 else if (dwType == REG_EXPAND_SZ)
618 char expanded[1024];
619 DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]);
620 if(ExpandEnvironmentStrings(data, expanded, dwExpandedSize))
622 value = expanded;
623 valueset = true;
628 RegCloseKey(hKey);
631 return valueset;
633 #else
634 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
635 KeyWOW64)
637 return false;
639 #endif
642 // Write a registry value.
643 // Example :
644 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
645 // => will set the data of the "default" value of the key
646 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
647 // => will set the data of the "Root" value of the key
649 #if defined(_WIN32) && !defined(__CYGWIN__)
650 bool SystemTools::WriteRegistryValue(const char *key, const char *value,
651 KeyWOW64 view)
653 kwsys_stl::string primary = key;
654 kwsys_stl::string second;
655 kwsys_stl::string valuename;
657 size_t start = primary.find("\\");
658 if (start == kwsys_stl::string::npos)
660 return false;
663 size_t valuenamepos = primary.find(";");
664 if (valuenamepos != kwsys_stl::string::npos)
666 valuename = primary.substr(valuenamepos+1);
669 second = primary.substr(start+1, valuenamepos-start-1);
670 primary = primary.substr(0, start);
672 HKEY primaryKey = HKEY_CURRENT_USER;
673 if (primary == "HKEY_CURRENT_USER")
675 primaryKey = HKEY_CURRENT_USER;
677 if (primary == "HKEY_CURRENT_CONFIG")
679 primaryKey = HKEY_CURRENT_CONFIG;
681 if (primary == "HKEY_CLASSES_ROOT")
683 primaryKey = HKEY_CLASSES_ROOT;
685 if (primary == "HKEY_LOCAL_MACHINE")
687 primaryKey = HKEY_LOCAL_MACHINE;
689 if (primary == "HKEY_USERS")
691 primaryKey = HKEY_USERS;
694 HKEY hKey;
695 DWORD dwDummy;
696 if(RegCreateKeyEx(primaryKey,
697 second.c_str(),
700 REG_OPTION_NON_VOLATILE,
701 SystemToolsMakeRegistryMode(KEY_WRITE, view),
702 NULL,
703 &hKey,
704 &dwDummy) != ERROR_SUCCESS)
706 return false;
709 if(RegSetValueEx(hKey,
710 (LPTSTR)valuename.c_str(),
712 REG_SZ,
713 (CONST BYTE *)value,
714 (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
716 return true;
718 return false;
720 #else
721 bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
723 return false;
725 #endif
727 // Delete a registry value.
728 // Example :
729 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
730 // => will delete the data of the "default" value of the key
731 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
732 // => will delete the data of the "Root" value of the key
734 #if defined(_WIN32) && !defined(__CYGWIN__)
735 bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
737 kwsys_stl::string primary = key;
738 kwsys_stl::string second;
739 kwsys_stl::string valuename;
741 size_t start = primary.find("\\");
742 if (start == kwsys_stl::string::npos)
744 return false;
747 size_t valuenamepos = primary.find(";");
748 if (valuenamepos != kwsys_stl::string::npos)
750 valuename = primary.substr(valuenamepos+1);
753 second = primary.substr(start+1, valuenamepos-start-1);
754 primary = primary.substr(0, start);
756 HKEY primaryKey = HKEY_CURRENT_USER;
757 if (primary == "HKEY_CURRENT_USER")
759 primaryKey = HKEY_CURRENT_USER;
761 if (primary == "HKEY_CURRENT_CONFIG")
763 primaryKey = HKEY_CURRENT_CONFIG;
765 if (primary == "HKEY_CLASSES_ROOT")
767 primaryKey = HKEY_CLASSES_ROOT;
769 if (primary == "HKEY_LOCAL_MACHINE")
771 primaryKey = HKEY_LOCAL_MACHINE;
773 if (primary == "HKEY_USERS")
775 primaryKey = HKEY_USERS;
778 HKEY hKey;
779 if(RegOpenKeyEx(primaryKey,
780 second.c_str(),
782 SystemToolsMakeRegistryMode(KEY_WRITE, view),
783 &hKey) != ERROR_SUCCESS)
785 return false;
787 else
789 if(RegDeleteValue(hKey,
790 (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
792 RegCloseKey(hKey);
793 return true;
796 return false;
798 #else
799 bool SystemTools::DeleteRegistryValue(const char *, KeyWOW64)
801 return false;
803 #endif
805 bool SystemTools::SameFile(const char* file1, const char* file2)
807 #ifdef _WIN32
808 HANDLE hFile1, hFile2;
810 hFile1 = CreateFile( file1,
811 GENERIC_READ,
812 FILE_SHARE_READ ,
813 NULL,
814 OPEN_EXISTING,
815 FILE_FLAG_BACKUP_SEMANTICS,
816 NULL
818 hFile2 = CreateFile( file2,
819 GENERIC_READ,
820 FILE_SHARE_READ,
821 NULL,
822 OPEN_EXISTING,
823 FILE_FLAG_BACKUP_SEMANTICS,
824 NULL
826 if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
828 if(hFile1 != INVALID_HANDLE_VALUE)
830 CloseHandle(hFile1);
832 if(hFile2 != INVALID_HANDLE_VALUE)
834 CloseHandle(hFile2);
836 return false;
839 BY_HANDLE_FILE_INFORMATION fiBuf1;
840 BY_HANDLE_FILE_INFORMATION fiBuf2;
841 GetFileInformationByHandle( hFile1, &fiBuf1 );
842 GetFileInformationByHandle( hFile2, &fiBuf2 );
843 CloseHandle(hFile1);
844 CloseHandle(hFile2);
845 return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
846 fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
847 fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
848 #else
849 struct stat fileStat1, fileStat2;
850 if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
852 // see if the files are the same file
853 // check the device inode and size
854 if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
855 memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
856 fileStat2.st_size == fileStat1.st_size
859 return true;
862 return false;
863 #endif
867 // return true if the file exists
868 bool SystemTools::FileExists(const char* filename, bool isFile)
870 #ifdef _MSC_VER
871 # define access _access
872 #endif
873 #ifndef R_OK
874 # define R_OK 04
875 #endif
877 #ifdef __SYLLABLE__
878 if ((filename !=0) && (*filename == 0))
880 return false;
882 #endif
884 if ( access(filename, R_OK) != 0 )
886 return false;
888 else
890 // If isFile is set return not FileIsDirectory,
891 // so this will only be true if it is a file
892 if(isFile)
894 return !SystemTools::FileIsDirectory(filename);
896 return true;
900 bool SystemTools::Touch(const char* filename, bool create)
902 if(create && !SystemTools::FileExists(filename))
904 FILE* file = fopen(filename, "a+b");
905 if(file)
907 fclose(file);
908 return true;
910 return false;
912 #ifdef _MSC_VER
913 #define utime _utime
914 #define utimbuf _utimbuf
915 #endif
916 struct stat fromStat;
917 if(stat(filename, &fromStat) < 0)
919 return false;
921 struct utimbuf buf;
922 buf.actime = fromStat.st_atime;
923 buf.modtime = static_cast<time_t>(SystemTools::GetTime());
924 if(utime(filename, &buf) < 0)
926 return false;
928 return true;
931 bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
932 int* result)
934 // Default to same time.
935 *result = 0;
936 #if !defined(_WIN32) || defined(__CYGWIN__)
937 // POSIX version. Use stat function to get file modification time.
938 struct stat s1;
939 if(stat(f1, &s1) != 0)
941 return false;
943 struct stat s2;
944 if(stat(f2, &s2) != 0)
946 return false;
948 # if KWSYS_STAT_HAS_ST_MTIM
949 // Compare using nanosecond resolution.
950 if(s1.st_mtim.tv_sec < s2.st_mtim.tv_sec)
952 *result = -1;
954 else if(s1.st_mtim.tv_sec > s2.st_mtim.tv_sec)
956 *result = 1;
958 else if(s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec)
960 *result = -1;
962 else if(s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec)
964 *result = 1;
966 # else
967 // Compare using 1 second resolution.
968 if(s1.st_mtime < s2.st_mtime)
970 *result = -1;
972 else if(s1.st_mtime > s2.st_mtime)
974 *result = 1;
976 # endif
977 #else
978 // Windows version. Get the modification time from extended file attributes.
979 WIN32_FILE_ATTRIBUTE_DATA f1d;
980 WIN32_FILE_ATTRIBUTE_DATA f2d;
981 if(!GetFileAttributesEx(f1, GetFileExInfoStandard, &f1d))
983 return false;
985 if(!GetFileAttributesEx(f2, GetFileExInfoStandard, &f2d))
987 return false;
990 // Compare the file times using resolution provided by system call.
991 *result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime);
992 #endif
993 return true;
997 // Return a capitalized string (i.e the first letter is uppercased, all other
998 // are lowercased)
999 kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s)
1001 kwsys_stl::string n;
1002 if(s.size() == 0)
1004 return n;
1006 n.resize(s.size());
1007 n[0] = static_cast<kwsys_stl::string::value_type>(toupper(s[0]));
1008 for (size_t i = 1; i < s.size(); i++)
1010 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1012 return n;
1015 // Return capitalized words
1016 kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s)
1018 kwsys_stl::string n(s);
1019 for (size_t i = 0; i < s.size(); i++)
1021 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1022 // MS has an assert that will fail if s[i] < 0; setting
1023 // LC_CTYPE using setlocale() does *not* help. Painful.
1024 if ((int)s[i] >= 0 && isalpha(s[i]) &&
1025 (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1]))))
1026 #else
1027 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
1028 #endif
1030 n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
1033 return n;
1036 // Return uncapitalized words
1037 kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s)
1039 kwsys_stl::string n(s);
1040 for (size_t i = 0; i < s.size(); i++)
1042 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1043 // MS has an assert that will fail if s[i] < 0; setting
1044 // LC_CTYPE using setlocale() does *not* help. Painful.
1045 if ((int)s[i] >= 0 && isalpha(s[i]) &&
1046 (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1]))))
1047 #else
1048 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
1049 #endif
1051 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1054 return n;
1057 // only works for words with at least two letters
1058 kwsys_stl::string SystemTools::AddSpaceBetweenCapitalizedWords(
1059 const kwsys_stl::string& s)
1061 kwsys_stl::string n;
1062 if (s.size())
1064 n.reserve(s.size());
1065 n += s[0];
1066 for (size_t i = 1; i < s.size(); i++)
1068 if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1]))
1070 n += ' ';
1072 n += s[i];
1075 return n;
1078 char* SystemTools::AppendStrings(const char* str1, const char* str2)
1080 if (!str1)
1082 return SystemTools::DuplicateString(str2);
1084 if (!str2)
1086 return SystemTools::DuplicateString(str1);
1088 size_t len1 = strlen(str1);
1089 char *newstr = new char[len1 + strlen(str2) + 1];
1090 if (!newstr)
1092 return 0;
1094 strcpy(newstr, str1);
1095 strcat(newstr + len1, str2);
1096 return newstr;
1099 char* SystemTools::AppendStrings(
1100 const char* str1, const char* str2, const char* str3)
1102 if (!str1)
1104 return SystemTools::AppendStrings(str2, str3);
1106 if (!str2)
1108 return SystemTools::AppendStrings(str1, str3);
1110 if (!str3)
1112 return SystemTools::AppendStrings(str1, str2);
1115 size_t len1 = strlen(str1), len2 = strlen(str2);
1116 char *newstr = new char[len1 + len2 + strlen(str3) + 1];
1117 if (!newstr)
1119 return 0;
1121 strcpy(newstr, str1);
1122 strcat(newstr + len1, str2);
1123 strcat(newstr + len1 + len2, str3);
1124 return newstr;
1127 // Return a lower case string
1128 kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s)
1130 kwsys_stl::string n;
1131 n.resize(s.size());
1132 for (size_t i = 0; i < s.size(); i++)
1134 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1136 return n;
1139 // Return a lower case string
1140 kwsys_stl::string SystemTools::UpperCase(const kwsys_stl::string& s)
1142 kwsys_stl::string n;
1143 n.resize(s.size());
1144 for (size_t i = 0; i < s.size(); i++)
1146 n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
1148 return n;
1151 // Count char in string
1152 size_t SystemTools::CountChar(const char* str, char c)
1154 size_t count = 0;
1156 if (str)
1158 while (*str)
1160 if (*str == c)
1162 ++count;
1164 ++str;
1167 return count;
1170 // Remove chars in string
1171 char* SystemTools::RemoveChars(const char* str, const char *toremove)
1173 if (!str)
1175 return NULL;
1177 char *clean_str = new char [strlen(str) + 1];
1178 char *ptr = clean_str;
1179 while (*str)
1181 const char *str2 = toremove;
1182 while (*str2 && *str != *str2)
1184 ++str2;
1186 if (!*str2)
1188 *ptr++ = *str;
1190 ++str;
1192 *ptr = '\0';
1193 return clean_str;
1196 // Remove chars in string
1197 char* SystemTools::RemoveCharsButUpperHex(const char* str)
1199 if (!str)
1201 return 0;
1203 char *clean_str = new char [strlen(str) + 1];
1204 char *ptr = clean_str;
1205 while (*str)
1207 if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'F'))
1209 *ptr++ = *str;
1211 ++str;
1213 *ptr = '\0';
1214 return clean_str;
1217 // Replace chars in string
1218 char* SystemTools::ReplaceChars(char* str, const char *toreplace, char replacement)
1220 if (str)
1222 char *ptr = str;
1223 while (*ptr)
1225 const char *ptr2 = toreplace;
1226 while (*ptr2)
1228 if (*ptr == *ptr2)
1230 *ptr = replacement;
1232 ++ptr2;
1234 ++ptr;
1237 return str;
1240 // Returns if string starts with another string
1241 bool SystemTools::StringStartsWith(const char* str1, const char* str2)
1243 if (!str1 || !str2)
1245 return false;
1247 size_t len1 = strlen(str1), len2 = strlen(str2);
1248 return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false;
1251 // Returns if string ends with another string
1252 bool SystemTools::StringEndsWith(const char* str1, const char* str2)
1254 if (!str1 || !str2)
1256 return false;
1258 size_t len1 = strlen(str1), len2 = strlen(str2);
1259 return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true : false;
1262 // Returns a pointer to the last occurence of str2 in str1
1263 const char* SystemTools::FindLastString(const char* str1, const char* str2)
1265 if (!str1 || !str2)
1267 return NULL;
1270 size_t len1 = strlen(str1), len2 = strlen(str2);
1271 if (len1 >= len2)
1273 const char *ptr = str1 + len1 - len2;
1276 if (!strncmp(ptr, str2, len2))
1278 return ptr;
1280 } while (ptr-- != str1);
1283 return NULL;
1286 // Duplicate string
1287 char* SystemTools::DuplicateString(const char* str)
1289 if (str)
1291 char *newstr = new char [strlen(str) + 1];
1292 return strcpy(newstr, str);
1294 return NULL;
1297 // Return a cropped string
1298 kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
1299 size_t max_len)
1301 if (!s.size() || max_len == 0 || max_len >= s.size())
1303 return s;
1306 kwsys_stl::string n;
1307 n.reserve(max_len);
1309 size_t middle = max_len / 2;
1311 n += s.substr(0, middle);
1312 n += s.substr(s.size() - (max_len - middle), kwsys_stl::string::npos);
1314 if (max_len > 2)
1316 n[middle] = '.';
1317 if (max_len > 3)
1319 n[middle - 1] = '.';
1320 if (max_len > 4)
1322 n[middle + 1] = '.';
1327 return n;
1330 //----------------------------------------------------------------------------
1331 kwsys_stl::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
1333 kwsys_stl::string path = p;
1334 kwsys_stl::vector<kwsys::String> paths;
1335 if(isPath && path[0] == '/')
1337 path.erase(path.begin());
1338 paths.push_back("/");
1340 kwsys_stl::string::size_type pos1 = 0;
1341 kwsys_stl::string::size_type pos2 = path.find(sep, pos1+1);
1342 while(pos2 != kwsys_stl::string::npos)
1344 paths.push_back(path.substr(pos1, pos2-pos1));
1345 pos1 = pos2+1;
1346 pos2 = path.find(sep, pos1+1);
1348 paths.push_back(path.substr(pos1, pos2-pos1));
1350 return paths;
1353 //----------------------------------------------------------------------------
1354 int SystemTools::EstimateFormatLength(const char *format, va_list ap)
1356 if (!format)
1358 return 0;
1361 // Quick-hack attempt at estimating the length of the string.
1362 // Should never under-estimate.
1364 // Start with the length of the format string itself.
1366 size_t length = strlen(format);
1368 // Increase the length for every argument in the format.
1370 const char* cur = format;
1371 while(*cur)
1373 if(*cur++ == '%')
1375 // Skip "%%" since it doesn't correspond to a va_arg.
1376 if(*cur != '%')
1378 while(!int(isalpha(*cur)))
1380 ++cur;
1382 switch (*cur)
1384 case 's':
1386 // Check the length of the string.
1387 char* s = va_arg(ap, char*);
1388 if(s)
1390 length += strlen(s);
1392 } break;
1393 case 'e':
1394 case 'f':
1395 case 'g':
1397 // Assume the argument contributes no more than 64 characters.
1398 length += 64;
1400 // Eat the argument.
1401 static_cast<void>(va_arg(ap, double));
1402 } break;
1403 default:
1405 // Assume the argument contributes no more than 64 characters.
1406 length += 64;
1408 // Eat the argument.
1409 static_cast<void>(va_arg(ap, int));
1410 } break;
1414 // Move past the characters just tested.
1415 ++cur;
1419 return static_cast<int>(length);
1422 kwsys_stl::string SystemTools::EscapeChars(
1423 const char *str,
1424 const char *chars_to_escape,
1425 char escape_char)
1427 kwsys_stl::string n;
1428 if (str)
1430 if (!chars_to_escape | !*chars_to_escape)
1432 n.append(str);
1434 else
1436 n.reserve(strlen(str));
1437 while (*str)
1439 const char *ptr = chars_to_escape;
1440 while (*ptr)
1442 if (*str == *ptr)
1444 n += escape_char;
1445 break;
1447 ++ptr;
1449 n += *str;
1450 ++str;
1454 return n;
1457 // convert windows slashes to unix slashes
1458 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
1460 const char* pathCString = path.c_str();
1461 bool hasDoubleSlash = false;
1463 const char* pos0 = pathCString;
1464 const char* pos1 = pathCString+1;
1465 for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos )
1467 // make sure we don't convert an escaped space to a unix slash
1468 if ( *pos0 == '\\' && *pos1 != ' ' )
1470 path[pos] = '/';
1473 // Also, reuse the loop to check for slash followed by another slash
1474 if (*pos1 == '/' && *(pos1+1) == '/' && !hasDoubleSlash)
1476 #ifdef _WIN32
1477 // However, on windows if the first characters are both slashes,
1478 // then keep them that way, so that network paths can be handled.
1479 if ( pos > 0)
1481 hasDoubleSlash = true;
1483 #else
1484 hasDoubleSlash = true;
1485 #endif
1488 pos0 ++;
1489 pos1 ++;
1492 if ( hasDoubleSlash )
1494 SystemTools::ReplaceString(path, "//", "/");
1497 // remove any trailing slash
1498 if(!path.empty())
1500 // if there is a tilda ~ then replace it with HOME
1501 pathCString = path.c_str();
1502 if(pathCString[0] == '~' && (pathCString[1] == '/' || pathCString[1] == '\0'))
1504 const char* homeEnv = SystemTools::GetEnv("HOME");
1505 if (homeEnv)
1507 path.replace(0,1,homeEnv);
1510 #ifdef HAVE_GETPWNAM
1511 else if(pathCString[0] == '~')
1513 kwsys_stl::string::size_type idx = path.find_first_of("/\0");
1514 kwsys_stl::string user = path.substr(1, idx-1);
1515 passwd* pw = getpwnam(user.c_str());
1516 if(pw)
1518 path.replace(0, idx, pw->pw_dir);
1521 #endif
1522 // remove trailing slash if the path is more than
1523 // a single /
1524 pathCString = path.c_str();
1525 if(path.size() > 1 && *(pathCString+(path.size()-1)) == '/')
1527 // if it is c:/ then do not remove the trailing slash
1528 if(!((path.size() == 3 && pathCString[1] == ':')))
1530 path = path.substr(0, path.size()-1);
1536 // change // to /, and escape any spaces in the path
1537 kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
1539 kwsys_stl::string ret = path;
1541 // remove // except at the beginning might be a cygwin drive
1542 kwsys_stl::string::size_type pos=0;
1543 while((pos = ret.find("//", pos)) != kwsys_stl::string::npos)
1545 ret.erase(pos, 1);
1547 // escape spaces and () in the path
1548 if(ret.find_first_of(" ") != kwsys_stl::string::npos)
1550 kwsys_stl::string result = "";
1551 char lastch = 1;
1552 for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
1554 // if it is already escaped then don't try to escape it again
1555 if((*ch == ' ') && lastch != '\\')
1557 result += '\\';
1559 result += *ch;
1560 lastch = *ch;
1562 ret = result;
1564 return ret;
1567 kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path)
1569 #if defined(_WIN32) && !defined(__CYGWIN__)
1570 return SystemTools::ConvertToWindowsOutputPath(path);
1571 #else
1572 return SystemTools::ConvertToUnixOutputPath(path);
1573 #endif
1576 // remove double slashes not at the start
1577 kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path)
1579 kwsys_stl::string ret;
1580 // make it big enough for all of path and double quotes
1581 ret.reserve(strlen(path)+3);
1582 // put path into the string
1583 ret.assign(path);
1584 ret = path;
1585 kwsys_stl::string::size_type pos = 0;
1586 // first convert all of the slashes
1587 while((pos = ret.find('/', pos)) != kwsys_stl::string::npos)
1589 ret[pos] = '\\';
1590 pos++;
1592 // check for really small paths
1593 if(ret.size() < 2)
1595 return ret;
1597 // now clean up a bit and remove double slashes
1598 // Only if it is not the first position in the path which is a network
1599 // path on windows
1600 pos = 1; // start at position 1
1601 if(ret[0] == '\"')
1603 pos = 2; // if the string is already quoted then start at 2
1604 if(ret.size() < 3)
1606 return ret;
1609 while((pos = ret.find("\\\\", pos)) != kwsys_stl::string::npos)
1611 ret.erase(pos, 1);
1613 // now double quote the path if it has spaces in it
1614 // and is not already double quoted
1615 if(ret.find(' ') != kwsys_stl::string::npos
1616 && ret[0] != '\"')
1618 ret.insert(static_cast<kwsys_stl::string::size_type>(0),
1619 static_cast<kwsys_stl::string::size_type>(1), '\"');
1620 ret.append(1, '\"');
1622 return ret;
1625 bool SystemTools::CopyFileIfDifferent(const char* source,
1626 const char* destination,
1627 bool copyPermissions)
1629 // special check for a destination that is a directory
1630 // FilesDiffer does not handle file to directory compare
1631 if(SystemTools::FileIsDirectory(destination))
1633 kwsys_stl::string new_destination = destination;
1634 SystemTools::ConvertToUnixSlashes(new_destination);
1635 new_destination += '/';
1636 kwsys_stl::string source_name = source;
1637 new_destination += SystemTools::GetFilenameName(source_name);
1638 if(SystemTools::FilesDiffer(source, new_destination.c_str()))
1640 return SystemTools::CopyFileAlways(source, destination,
1641 copyPermissions);
1643 else
1645 // the files are the same so the copy is done return
1646 // true
1647 return true;
1650 // source and destination are files so do a copy if they
1651 // are different
1652 if(SystemTools::FilesDiffer(source, destination))
1654 return SystemTools::CopyFileAlways(source, destination, copyPermissions);
1656 // at this point the files must be the same so return true
1657 return true;
1660 #define KWSYS_ST_BUFFER 4096
1662 bool SystemTools::FilesDiffer(const char* source,
1663 const char* destination)
1665 struct stat statSource;
1666 if (stat(source, &statSource) != 0)
1668 return true;
1671 struct stat statDestination;
1672 if (stat(destination, &statDestination) != 0)
1674 return true;
1677 if(statSource.st_size != statDestination.st_size)
1679 return true;
1682 if(statSource.st_size == 0)
1684 return false;
1687 #if defined(_WIN32) || defined(__CYGWIN__)
1688 kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
1689 kwsys_ios::ios::in));
1690 kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
1691 kwsys_ios::ios::in));
1692 #else
1693 kwsys_ios::ifstream finSource(source);
1694 kwsys_ios::ifstream finDestination(destination);
1695 #endif
1696 if(!finSource || !finDestination)
1698 return true;
1701 // Compare the files a block at a time.
1702 char source_buf[KWSYS_ST_BUFFER];
1703 char dest_buf[KWSYS_ST_BUFFER];
1704 off_t nleft = statSource.st_size;
1705 while(nleft > 0)
1707 // Read a block from each file.
1708 kwsys_ios::streamsize nnext = (nleft > KWSYS_ST_BUFFER)? KWSYS_ST_BUFFER : static_cast<kwsys_ios::streamsize>(nleft);
1709 finSource.read(source_buf, nnext);
1710 finDestination.read(dest_buf, nnext);
1712 // If either failed to read assume they are different.
1713 if(static_cast<kwsys_ios::streamsize>(finSource.gcount()) != nnext ||
1714 static_cast<kwsys_ios::streamsize>(finDestination.gcount()) != nnext)
1716 return true;
1719 // If this block differs the file differs.
1720 if(memcmp(static_cast<const void*>(source_buf),
1721 static_cast<const void*>(dest_buf),
1722 static_cast<size_t>(nnext)) != 0)
1724 return true;
1727 // Update the byte count remaining.
1728 nleft -= nnext;
1731 // No differences found.
1732 return false;
1736 //----------------------------------------------------------------------------
1738 * Copy a file named by "source" to the file named by "destination".
1740 bool SystemTools::CopyFileAlways(const char* source, const char* destination,
1741 bool copyPermissions)
1743 // If files are the same do not copy
1744 if ( SystemTools::SameFile(source, destination) )
1746 return true;
1748 mode_t perm = 0;
1749 bool perms = SystemTools::GetPermissions(source, perm);
1751 const int bufferSize = 4096;
1752 char buffer[bufferSize];
1754 // If destination is a directory, try to create a file with the same
1755 // name as the source in that directory.
1757 kwsys_stl::string new_destination;
1758 if(SystemTools::FileExists(destination) &&
1759 SystemTools::FileIsDirectory(destination))
1761 new_destination = destination;
1762 SystemTools::ConvertToUnixSlashes(new_destination);
1763 new_destination += '/';
1764 kwsys_stl::string source_name = source;
1765 new_destination += SystemTools::GetFilenameName(source_name);
1766 destination = new_destination.c_str();
1769 // Create destination directory
1771 kwsys_stl::string destination_dir = destination;
1772 destination_dir = SystemTools::GetFilenamePath(destination_dir);
1773 SystemTools::MakeDirectory(destination_dir.c_str());
1775 // Open files
1777 #if defined(_WIN32) || defined(__CYGWIN__)
1778 kwsys_ios::ifstream fin(source,
1779 kwsys_ios::ios::binary | kwsys_ios::ios::in);
1780 #else
1781 kwsys_ios::ifstream fin(source);
1782 #endif
1783 if(!fin)
1785 return false;
1788 // try and remove the destination file so that read only destination files
1789 // can be written to.
1790 // If the remove fails continue so that files in read only directories
1791 // that do not allow file removal can be modified.
1792 SystemTools::RemoveFile(destination);
1794 #if defined(_WIN32) || defined(__CYGWIN__)
1795 kwsys_ios::ofstream fout(destination,
1796 kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1797 #else
1798 kwsys_ios::ofstream fout(destination,
1799 kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1800 #endif
1801 if(!fout)
1803 return false;
1806 // This copy loop is very sensitive on certain platforms with
1807 // slightly broken stream libraries (like HPUX). Normally, it is
1808 // incorrect to not check the error condition on the fin.read()
1809 // before using the data, but the fin.gcount() will be zero if an
1810 // error occurred. Therefore, the loop should be safe everywhere.
1811 while(fin)
1813 fin.read(buffer, bufferSize);
1814 if(fin.gcount())
1816 fout.write(buffer, fin.gcount());
1820 // Make sure the operating system has finished writing the file
1821 // before closing it. This will ensure the file is finished before
1822 // the check below.
1823 fout.flush();
1825 fin.close();
1826 fout.close();
1828 // More checks.
1829 struct stat statSource, statDestination;
1830 statSource.st_size = 12345;
1831 statDestination.st_size = 12345;
1832 if(stat(source, &statSource) != 0)
1834 return false;
1836 else if(stat(destination, &statDestination) != 0)
1838 return false;
1840 else if(statSource.st_size != statDestination.st_size)
1842 return false;
1844 if ( copyPermissions && perms )
1846 if ( !SystemTools::SetPermissions(destination, perm) )
1848 return false;
1851 return true;
1854 //----------------------------------------------------------------------------
1855 bool SystemTools::CopyAFile(const char* source, const char* destination,
1856 bool always, bool copyPermissions)
1858 if(always)
1860 return SystemTools::CopyFileAlways(source, destination, copyPermissions);
1862 else
1864 return SystemTools::CopyFileIfDifferent(source, destination, copyPermissions);
1869 * Copy a directory content from "source" directory to the directory named by
1870 * "destination".
1872 bool SystemTools::CopyADirectory(const char* source, const char* destination,
1873 bool always, bool copyPermissions)
1875 Directory dir;
1876 dir.Load(source);
1877 size_t fileNum;
1878 if ( !SystemTools::MakeDirectory(destination) )
1880 return false;
1882 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
1884 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
1885 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
1887 kwsys_stl::string fullPath = source;
1888 fullPath += "/";
1889 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1890 if(SystemTools::FileIsDirectory(fullPath.c_str()))
1892 kwsys_stl::string fullDestPath = destination;
1893 fullDestPath += "/";
1894 fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1895 if (!SystemTools::CopyADirectory(fullPath.c_str(),
1896 fullDestPath.c_str(),
1897 always,
1898 copyPermissions))
1900 return false;
1903 else
1905 if(!SystemTools::CopyAFile(fullPath.c_str(), destination, always,
1906 copyPermissions))
1908 return false;
1914 return true;
1918 // return size of file; also returns zero if no file exists
1919 unsigned long SystemTools::FileLength(const char* filename)
1921 struct stat fs;
1922 if (stat(filename, &fs) != 0)
1924 return 0;
1926 else
1928 return static_cast<unsigned long>(fs.st_size);
1932 int SystemTools::Strucmp(const char *s1, const char *s2)
1934 // lifted from Graphvis http://www.graphviz.org
1935 while ((*s1 != '\0')
1936 && (tolower(*s1) == tolower(*s2)))
1938 s1++;
1939 s2++;
1942 return tolower(*s1) - tolower(*s2);
1945 // return file's modified time
1946 long int SystemTools::ModifiedTime(const char* filename)
1948 struct stat fs;
1949 if (stat(filename, &fs) != 0)
1951 return 0;
1953 else
1955 return static_cast<long int>(fs.st_mtime);
1959 // return file's creation time
1960 long int SystemTools::CreationTime(const char* filename)
1962 struct stat fs;
1963 if (stat(filename, &fs) != 0)
1965 return 0;
1967 else
1969 return fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0;
1973 bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt)
1975 if (!str || !tmt || strlen(str) > 11)
1977 return false;
1980 struct tm tmt2;
1982 // __DATE__
1983 // The compilation date of the current source file. The date is a string
1984 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
1985 // dates generated by the library function asctime declared in TIME.H.
1987 // index: 012345678901
1988 // format: Mmm dd yyyy
1989 // example: Dec 19 2003
1991 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1993 char buffer[12];
1994 strcpy(buffer, str);
1996 buffer[3] = 0;
1997 char *ptr = strstr(month_names, buffer);
1998 if (!ptr)
2000 return false;
2003 int month = static_cast<int>((ptr - month_names) / 3);
2004 int day = atoi(buffer + 4);
2005 int year = atoi(buffer + 7);
2007 tmt2.tm_isdst = -1;
2008 tmt2.tm_hour = 0;
2009 tmt2.tm_min = 0;
2010 tmt2.tm_sec = 0;
2011 tmt2.tm_wday = 0;
2012 tmt2.tm_yday = 0;
2013 tmt2.tm_mday = day;
2014 tmt2.tm_mon = month;
2015 tmt2.tm_year = year - 1900;
2017 *tmt = mktime(&tmt2);
2018 return true;
2021 bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt)
2023 if (!str || !tmt || strlen(str) > 26)
2025 return false;
2028 struct tm tmt2;
2030 // __TIMESTAMP__
2031 // The date and time of the last modification of the current source file,
2032 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
2033 /// where Ddd is the abbreviated day of the week and Date is an integer
2034 // from 1 to 31.
2036 // index: 0123456789
2037 // 0123456789
2038 // 0123456789
2039 // format: Ddd Mmm Date hh:mm:ss yyyy
2040 // example: Fri Dec 19 14:34:58 2003
2042 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
2044 char buffer[27];
2045 strcpy(buffer, str);
2047 buffer[7] = 0;
2048 char *ptr = strstr(month_names, buffer + 4);
2049 if (!ptr)
2051 return false;
2054 int month = static_cast<int>((ptr - month_names) / 3);
2055 int day = atoi(buffer + 8);
2056 int hour = atoi(buffer + 11);
2057 int min = atoi(buffer + 14);
2058 int sec = atoi(buffer + 17);
2059 int year = atoi(buffer + 20);
2061 tmt2.tm_isdst = -1;
2062 tmt2.tm_hour = hour;
2063 tmt2.tm_min = min;
2064 tmt2.tm_sec = sec;
2065 tmt2.tm_wday = 0;
2066 tmt2.tm_yday = 0;
2067 tmt2.tm_mday = day;
2068 tmt2.tm_mon = month;
2069 tmt2.tm_year = year - 1900;
2071 *tmt = mktime(&tmt2);
2072 return true;
2075 kwsys_stl::string SystemTools::GetLastSystemError()
2077 int e = errno;
2078 return strerror(e);
2081 bool SystemTools::RemoveFile(const char* source)
2083 #ifdef _WIN32
2084 mode_t mode;
2085 if ( !SystemTools::GetPermissions(source, mode) )
2087 return false;
2089 /* Win32 unlink is stupid --- it fails if the file is read-only */
2090 SystemTools::SetPermissions(source, S_IWRITE);
2091 #endif
2092 bool res = unlink(source) != 0 ? false : true;
2093 #ifdef _WIN32
2094 if ( !res )
2096 SystemTools::SetPermissions(source, mode);
2098 #endif
2099 return res;
2102 bool SystemTools::RemoveADirectory(const char* source)
2104 Directory dir;
2105 dir.Load(source);
2106 size_t fileNum;
2107 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
2109 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
2110 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
2112 kwsys_stl::string fullPath = source;
2113 fullPath += "/";
2114 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
2115 if(SystemTools::FileIsDirectory(fullPath.c_str()) &&
2116 !SystemTools::FileIsSymlink(fullPath.c_str()))
2118 if (!SystemTools::RemoveADirectory(fullPath.c_str()))
2120 return false;
2123 else
2125 if(!SystemTools::RemoveFile(fullPath.c_str()))
2127 return false;
2133 return (Rmdir(source) == 0);
2138 size_t SystemTools::GetMaximumFilePathLength()
2140 return KWSYS_SYSTEMTOOLS_MAXPATH;
2144 * Find the file the given name. Searches the given path and then
2145 * the system search path. Returns the full path to the file if it is
2146 * found. Otherwise, the empty string is returned.
2148 kwsys_stl::string SystemTools
2149 ::FindName(const char* name,
2150 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2151 bool no_system_path)
2153 // Add the system search path to our path first
2154 kwsys_stl::vector<kwsys_stl::string> path;
2155 if (!no_system_path)
2157 SystemTools::GetPath(path, "CMAKE_FILE_PATH");
2158 SystemTools::GetPath(path);
2160 // now add the additional paths
2162 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
2163 i != userPaths.end(); ++i)
2165 path.push_back(*i);
2168 // Add a trailing slash to all paths to aid the search process.
2170 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2171 i != path.end(); ++i)
2173 kwsys_stl::string& p = *i;
2174 if(p.empty() || p[p.size()-1] != '/')
2176 p += "/";
2180 // now look for the file
2181 kwsys_stl::string tryPath;
2182 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
2183 p != path.end(); ++p)
2185 tryPath = *p;
2186 tryPath += name;
2187 if(SystemTools::FileExists(tryPath.c_str()))
2189 return tryPath;
2192 // Couldn't find the file.
2193 return "";
2197 * Find the file the given name. Searches the given path and then
2198 * the system search path. Returns the full path to the file if it is
2199 * found. Otherwise, the empty string is returned.
2201 kwsys_stl::string SystemTools
2202 ::FindFile(const char* name,
2203 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2204 bool no_system_path)
2206 kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
2207 if(tryPath != "" && !SystemTools::FileIsDirectory(tryPath.c_str()))
2209 return SystemTools::CollapseFullPath(tryPath.c_str());
2211 // Couldn't find the file.
2212 return "";
2216 * Find the directory the given name. Searches the given path and then
2217 * the system search path. Returns the full path to the directory if it is
2218 * found. Otherwise, the empty string is returned.
2220 kwsys_stl::string SystemTools
2221 ::FindDirectory(const char* name,
2222 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2223 bool no_system_path)
2225 kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
2226 if(tryPath != "" && SystemTools::FileIsDirectory(tryPath.c_str()))
2228 return SystemTools::CollapseFullPath(tryPath.c_str());
2230 // Couldn't find the file.
2231 return "";
2235 * Find the executable with the given name. Searches the given path and then
2236 * the system search path. Returns the full path to the executable if it is
2237 * found. Otherwise, the empty string is returned.
2239 kwsys_stl::string SystemTools::FindProgram(
2240 const char* nameIn,
2241 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2242 bool no_system_path)
2244 if(!nameIn || !*nameIn)
2246 return "";
2248 kwsys_stl::string name = nameIn;
2249 kwsys_stl::vector<kwsys_stl::string> extensions;
2250 #if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
2251 bool hasExtension = false;
2252 // check to see if the name already has a .xxx at
2253 // the end of it
2254 if(name.size() > 3 && name[name.size()-4] == '.')
2256 hasExtension = true;
2258 // on windows try .com then .exe
2259 if(!hasExtension)
2261 extensions.push_back(".com");
2262 extensions.push_back(".exe");
2264 #endif
2265 kwsys_stl::string tryPath;
2267 // first try with extensions if the os supports them
2268 if(extensions.size())
2270 for(kwsys_stl::vector<kwsys_stl::string>::iterator i =
2271 extensions.begin(); i != extensions.end(); ++i)
2273 tryPath = name;
2274 tryPath += *i;
2275 if(SystemTools::FileExists(tryPath.c_str()) &&
2276 !SystemTools::FileIsDirectory(tryPath.c_str()))
2278 return SystemTools::CollapseFullPath(tryPath.c_str());
2282 // now try just the name
2283 tryPath = name;
2284 if(SystemTools::FileExists(tryPath.c_str()) &&
2285 !SystemTools::FileIsDirectory(tryPath.c_str()))
2287 return SystemTools::CollapseFullPath(tryPath.c_str());
2289 // now construct the path
2290 kwsys_stl::vector<kwsys_stl::string> path;
2291 // Add the system search path to our path.
2292 if (!no_system_path)
2294 SystemTools::GetPath(path);
2296 // now add the additional paths
2298 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i =
2299 userPaths.begin(); i != userPaths.end(); ++i)
2301 path.push_back(*i);
2304 // Add a trailing slash to all paths to aid the search process.
2306 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2307 i != path.end(); ++i)
2309 kwsys_stl::string& p = *i;
2310 if(p.empty() || p[p.size()-1] != '/')
2312 p += "/";
2316 // Try each path
2317 for(kwsys_stl::vector<kwsys_stl::string>::iterator p = path.begin();
2318 p != path.end(); ++p)
2320 #ifdef _WIN32
2321 // Remove double quotes from the path on windows
2322 SystemTools::ReplaceString(*p, "\"", "");
2323 #endif
2324 // first try with extensions
2325 if(extensions.size())
2327 for(kwsys_stl::vector<kwsys_stl::string>::iterator ext
2328 = extensions.begin(); ext != extensions.end(); ++ext)
2330 tryPath = *p;
2331 tryPath += name;
2332 tryPath += *ext;
2333 if(SystemTools::FileExists(tryPath.c_str()) &&
2334 !SystemTools::FileIsDirectory(tryPath.c_str()))
2336 return SystemTools::CollapseFullPath(tryPath.c_str());
2340 // now try it without them
2341 tryPath = *p;
2342 tryPath += name;
2343 if(SystemTools::FileExists(tryPath.c_str()) &&
2344 !SystemTools::FileIsDirectory(tryPath.c_str()))
2346 return SystemTools::CollapseFullPath(tryPath.c_str());
2349 // Couldn't find the program.
2350 return "";
2353 kwsys_stl::string SystemTools::FindProgram(
2354 const kwsys_stl::vector<kwsys_stl::string>& names,
2355 const kwsys_stl::vector<kwsys_stl::string>& path,
2356 bool noSystemPath)
2358 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator it = names.begin();
2359 it != names.end() ; ++it)
2361 // Try to find the program.
2362 kwsys_stl::string result = SystemTools::FindProgram(it->c_str(),
2363 path,
2364 noSystemPath);
2365 if ( !result.empty() )
2367 return result;
2370 return "";
2374 * Find the library with the given name. Searches the given path and then
2375 * the system search path. Returns the full path to the library if it is
2376 * found. Otherwise, the empty string is returned.
2378 kwsys_stl::string SystemTools
2379 ::FindLibrary(const char* name,
2380 const kwsys_stl::vector<kwsys_stl::string>& userPaths)
2382 // See if the executable exists as written.
2383 if(SystemTools::FileExists(name) &&
2384 !SystemTools::FileIsDirectory(name))
2386 return SystemTools::CollapseFullPath(name);
2389 // Add the system search path to our path.
2390 kwsys_stl::vector<kwsys_stl::string> path;
2391 SystemTools::GetPath(path);
2392 // now add the additional paths
2394 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
2395 i != userPaths.end(); ++i)
2397 path.push_back(*i);
2400 // Add a trailing slash to all paths to aid the search process.
2402 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2403 i != path.end(); ++i)
2405 kwsys_stl::string& p = *i;
2406 if(p.empty() || p[p.size()-1] != '/')
2408 p += "/";
2412 kwsys_stl::string tryPath;
2413 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
2414 p != path.end(); ++p)
2416 #if defined(__APPLE__)
2417 tryPath = *p;
2418 tryPath += name;
2419 tryPath += ".framework";
2420 if(SystemTools::FileExists(tryPath.c_str())
2421 && SystemTools::FileIsDirectory(tryPath.c_str()))
2423 return SystemTools::CollapseFullPath(tryPath.c_str());
2425 #endif
2426 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
2427 tryPath = *p;
2428 tryPath += name;
2429 tryPath += ".lib";
2430 if(SystemTools::FileExists(tryPath.c_str())
2431 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2433 return SystemTools::CollapseFullPath(tryPath.c_str());
2435 #else
2436 tryPath = *p;
2437 tryPath += "lib";
2438 tryPath += name;
2439 tryPath += ".so";
2440 if(SystemTools::FileExists(tryPath.c_str())
2441 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2443 return SystemTools::CollapseFullPath(tryPath.c_str());
2445 tryPath = *p;
2446 tryPath += "lib";
2447 tryPath += name;
2448 tryPath += ".a";
2449 if(SystemTools::FileExists(tryPath.c_str())
2450 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2452 return SystemTools::CollapseFullPath(tryPath.c_str());
2454 tryPath = *p;
2455 tryPath += "lib";
2456 tryPath += name;
2457 tryPath += ".sl";
2458 if(SystemTools::FileExists(tryPath.c_str())
2459 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2461 return SystemTools::CollapseFullPath(tryPath.c_str());
2463 tryPath = *p;
2464 tryPath += "lib";
2465 tryPath += name;
2466 tryPath += ".dylib";
2467 if(SystemTools::FileExists(tryPath.c_str())
2468 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2470 return SystemTools::CollapseFullPath(tryPath.c_str());
2472 tryPath = *p;
2473 tryPath += "lib";
2474 tryPath += name;
2475 tryPath += ".dll";
2476 if(SystemTools::FileExists(tryPath.c_str())
2477 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2479 return SystemTools::CollapseFullPath(tryPath.c_str());
2481 #endif
2484 // Couldn't find the library.
2485 return "";
2488 kwsys_stl::string SystemTools::GetRealPath(const char* path)
2490 kwsys_stl::string ret;
2491 Realpath(path, ret);
2492 return ret;
2495 bool SystemTools::FileIsDirectory(const char* name)
2497 // Remove any trailing slash from the name.
2498 char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
2499 size_t last = strlen(name)-1;
2500 if(last > 0 && (name[last] == '/' || name[last] == '\\')
2501 && strcmp(name, "/") !=0)
2503 memcpy(buffer, name, last);
2504 buffer[last] = 0;
2505 name = buffer;
2508 // Now check the file node type.
2509 struct stat fs;
2510 if(stat(name, &fs) == 0)
2512 #if defined( _WIN32 )
2513 return ((fs.st_mode & _S_IFDIR) != 0);
2514 #else
2515 return S_ISDIR(fs.st_mode);
2516 #endif
2518 else
2520 return false;
2524 bool SystemTools::FileIsSymlink(const char* name)
2526 #if defined( _WIN32 )
2527 (void)name;
2528 return false;
2529 #else
2530 struct stat fs;
2531 if(lstat(name, &fs) == 0)
2533 return S_ISLNK(fs.st_mode);
2535 else
2537 return false;
2539 #endif
2542 #if defined(_WIN32) && !defined(__CYGWIN__)
2543 bool SystemTools::CreateSymlink(const char*, const char*)
2545 return false;
2547 #else
2548 bool SystemTools::CreateSymlink(const char* origName, const char* newName)
2550 return symlink(origName, newName) >= 0;
2552 #endif
2554 #if defined(_WIN32) && !defined(__CYGWIN__)
2555 bool SystemTools::ReadSymlink(const char*, kwsys_stl::string&)
2557 return false;
2559 #else
2560 bool SystemTools::ReadSymlink(const char* newName,
2561 kwsys_stl::string& origName)
2563 char buf[KWSYS_SYSTEMTOOLS_MAXPATH+1];
2564 int count =
2565 static_cast<int>(readlink(newName, buf, KWSYS_SYSTEMTOOLS_MAXPATH));
2566 if(count >= 0)
2568 // Add null-terminator.
2569 buf[count] = 0;
2570 origName = buf;
2571 return true;
2573 else
2575 return false;
2578 #endif
2580 int SystemTools::ChangeDirectory(const char *dir)
2582 return Chdir(dir);
2585 kwsys_stl::string SystemTools::GetCurrentWorkingDirectory(bool collapse)
2587 char buf[2048];
2588 const char* cwd = Getcwd(buf, 2048);
2589 kwsys_stl::string path;
2590 if ( cwd )
2592 path = cwd;
2594 if(collapse)
2596 return SystemTools::CollapseFullPath(path.c_str());
2598 return path;
2601 kwsys_stl::string SystemTools::GetProgramPath(const char* in_name)
2603 kwsys_stl::string dir, file;
2604 SystemTools::SplitProgramPath(in_name, dir, file);
2605 return dir;
2608 bool SystemTools::SplitProgramPath(const char* in_name,
2609 kwsys_stl::string& dir,
2610 kwsys_stl::string& file,
2611 bool)
2613 dir = in_name;
2614 file = "";
2615 SystemTools::ConvertToUnixSlashes(dir);
2617 if(!SystemTools::FileIsDirectory(dir.c_str()))
2619 kwsys_stl::string::size_type slashPos = dir.rfind("/");
2620 if(slashPos != kwsys_stl::string::npos)
2622 file = dir.substr(slashPos+1);
2623 dir = dir.substr(0, slashPos);
2625 else
2627 file = dir;
2628 dir = "";
2631 if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str()))
2633 kwsys_stl::string oldDir = in_name;
2634 SystemTools::ConvertToUnixSlashes(oldDir);
2635 dir = in_name;
2636 return false;
2638 return true;
2641 bool SystemTools::FindProgramPath(const char* argv0,
2642 kwsys_stl::string& pathOut,
2643 kwsys_stl::string& errorMsg,
2644 const char* exeName,
2645 const char* buildDir,
2646 const char* installPrefix )
2648 kwsys_stl::vector<kwsys_stl::string> failures;
2649 kwsys_stl::string self = argv0 ? argv0 : "";
2650 failures.push_back(self);
2651 SystemTools::ConvertToUnixSlashes(self);
2652 self = SystemTools::FindProgram(self.c_str());
2653 if(!SystemTools::FileExists(self.c_str()))
2655 if(buildDir)
2657 kwsys_stl::string intdir = ".";
2658 #ifdef CMAKE_INTDIR
2659 intdir = CMAKE_INTDIR;
2660 #endif
2661 self = buildDir;
2662 self += "/bin/";
2663 self += intdir;
2664 self += "/";
2665 self += exeName;
2666 self += SystemTools::GetExecutableExtension();
2669 if(installPrefix)
2671 if(!SystemTools::FileExists(self.c_str()))
2673 failures.push_back(self);
2674 self = installPrefix;
2675 self += "/bin/";
2676 self += exeName;
2679 if(!SystemTools::FileExists(self.c_str()))
2681 failures.push_back(self);
2682 kwsys_ios::ostringstream msg;
2683 msg << "Can not find the command line program ";
2684 if (exeName)
2686 msg << exeName;
2688 msg << "\n";
2689 if (argv0)
2691 msg << " argv[0] = \"" << argv0 << "\"\n";
2693 msg << " Attempted paths:\n";
2694 kwsys_stl::vector<kwsys_stl::string>::iterator i;
2695 for(i=failures.begin(); i != failures.end(); ++i)
2697 msg << " \"" << i->c_str() << "\"\n";
2699 errorMsg = msg.str();
2700 return false;
2702 pathOut = self;
2703 return true;
2707 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative)
2709 return SystemTools::CollapseFullPath(in_relative, 0);
2712 void SystemTools::AddTranslationPath(const char * a, const char * b)
2714 kwsys_stl::string path_a = a;
2715 kwsys_stl::string path_b = b;
2716 SystemTools::ConvertToUnixSlashes(path_a);
2717 SystemTools::ConvertToUnixSlashes(path_b);
2718 // First check this is a directory path, since we don't want the table to
2719 // grow too fat
2720 if( SystemTools::FileIsDirectory( path_a.c_str() ) )
2722 // Make sure the path is a full path and does not contain no '..'
2723 // Ken--the following code is incorrect. .. can be in a valid path
2724 // for example /home/martink/MyHubba...Hubba/Src
2725 if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..")
2726 == kwsys_stl::string::npos )
2728 // Before inserting make sure path ends with '/'
2729 if(path_a.size() && path_a[path_a.size() -1] != '/')
2731 path_a += '/';
2733 if(path_b.size() && path_b[path_b.size() -1] != '/')
2735 path_b += '/';
2737 if( !(path_a == path_b) )
2739 SystemTools::TranslationMap->insert(
2740 SystemToolsTranslationMap::value_type(path_a, path_b));
2746 void SystemTools::AddKeepPath(const char* dir)
2748 kwsys_stl::string cdir;
2749 Realpath(SystemTools::CollapseFullPath(dir).c_str(), cdir);
2750 SystemTools::AddTranslationPath(cdir.c_str(), dir);
2753 void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
2755 // Do not translate paths that are too short to have meaningful
2756 // translations.
2757 if(path.size() < 2)
2759 return;
2762 // Always add a trailing slash before translation. It does not
2763 // matter if this adds an extra slash, but we do not want to
2764 // translate part of a directory (like the foo part of foo-dir).
2765 path += "/";
2767 // In case a file was specified we still have to go through this:
2768 // Now convert any path found in the table back to the one desired:
2769 kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>::const_iterator it;
2770 for(it = SystemTools::TranslationMap->begin();
2771 it != SystemTools::TranslationMap->end();
2772 ++it )
2774 // We need to check of the path is a substring of the other path
2775 if(path.find( it->first ) == 0)
2777 path = path.replace( 0, it->first.size(), it->second);
2781 // Remove the trailing slash we added before.
2782 path.erase(path.end()-1, path.end());
2785 void
2786 SystemToolsAppendComponents(
2787 kwsys_stl::vector<kwsys_stl::string>& out_components,
2788 kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
2789 kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
2791 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = first;
2792 i != last; ++i)
2794 if(*i == "..")
2796 if(out_components.begin() != out_components.end())
2798 out_components.erase(out_components.end()-1, out_components.end());
2801 else if(!(*i == ".") && !(*i == ""))
2803 out_components.push_back(*i);
2808 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
2809 const char* in_base)
2811 // Collect the output path components.
2812 kwsys_stl::vector<kwsys_stl::string> out_components;
2814 // Split the input path components.
2815 kwsys_stl::vector<kwsys_stl::string> path_components;
2816 SystemTools::SplitPath(in_path, path_components);
2818 // If the input path is relative, start with a base path.
2819 if(path_components[0].length() == 0)
2821 kwsys_stl::vector<kwsys_stl::string> base_components;
2822 if(in_base)
2824 // Use the given base path.
2825 SystemTools::SplitPath(in_base, base_components);
2827 else
2829 // Use the current working directory as a base path.
2830 char buf[2048];
2831 if(const char* cwd = Getcwd(buf, 2048))
2833 SystemTools::SplitPath(cwd, base_components);
2835 else
2837 // ??
2841 // Append base path components to the output path.
2842 out_components.push_back(base_components[0]);
2843 SystemToolsAppendComponents(out_components,
2844 base_components.begin()+1,
2845 base_components.end());
2848 // Append input path components to the output path.
2849 SystemToolsAppendComponents(out_components,
2850 path_components.begin(),
2851 path_components.end());
2853 // Transform the path back to a string.
2854 kwsys_stl::string newPath = SystemTools::JoinPath(out_components);
2856 // Update the translation table with this potentially new path. I am not
2857 // sure why this line is here, it seems really questionable, but yet I
2858 // would put good money that if I remove it something will break, basically
2859 // from what I can see it created a mapping from the collapsed path, to be
2860 // replaced by the input path, which almost completely does the opposite of
2861 // this function, the only thing preventing this from happening a lot is
2862 // that if the in_path has a .. in it, then it is not added to the
2863 // translation table. So for most calls this either does nothing due to the
2864 // .. or it adds a translation between identical paths as nothing was
2865 // collapsed, so I am going to try to comment it out, and see what hits the
2866 // fan, hopefully quickly.
2867 // Commented out line below:
2868 //SystemTools::AddTranslationPath(newPath.c_str(), in_path);
2870 SystemTools::CheckTranslationPath(newPath);
2871 #ifdef _WIN32
2872 newPath = SystemTools::GetActualCaseForPath(newPath.c_str());
2873 SystemTools::ConvertToUnixSlashes(newPath);
2874 #endif
2875 // Return the reconstructed path.
2876 return newPath;
2879 // compute the relative path from here to there
2880 kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remote)
2882 if(!SystemTools::FileIsFullPath(local))
2884 return "";
2886 if(!SystemTools::FileIsFullPath(remote))
2888 return "";
2891 // split up both paths into arrays of strings using / as a separator
2892 kwsys_stl::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true);
2893 kwsys_stl::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true);
2894 kwsys_stl::vector<kwsys::String> commonPath; // store shared parts of path in this array
2895 kwsys_stl::vector<kwsys::String> finalPath; // store the final relative path here
2896 // count up how many matching directory names there are from the start
2897 unsigned int sameCount = 0;
2898 while(
2899 ((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1)))
2901 // for windows and apple do a case insensitive string compare
2902 #if defined(_WIN32) || defined(__APPLE__)
2903 SystemTools::Strucmp(localSplit[sameCount].c_str(),
2904 remoteSplit[sameCount].c_str()) == 0
2905 #else
2906 localSplit[sameCount] == remoteSplit[sameCount]
2907 #endif
2910 // put the common parts of the path into the commonPath array
2911 commonPath.push_back(localSplit[sameCount]);
2912 // erase the common parts of the path from the original path arrays
2913 localSplit[sameCount] = "";
2914 remoteSplit[sameCount] = "";
2915 sameCount++;
2918 // If there is nothing in common at all then just return the full
2919 // path. This is the case only on windows when the paths have
2920 // different drive letters. On unix two full paths always at least
2921 // have the root "/" in common so we will return a relative path
2922 // that passes through the root directory.
2923 if(sameCount == 0)
2925 return remote;
2928 // for each entry that is not common in the local path
2929 // add a ../ to the finalpath array, this gets us out of the local
2930 // path into the remote dir
2931 for(unsigned int i = 0; i < localSplit.size(); ++i)
2933 if(localSplit[i].size())
2935 finalPath.push_back("../");
2938 // for each entry that is not common in the remote path add it
2939 // to the final path.
2940 for(kwsys_stl::vector<String>::iterator vit = remoteSplit.begin();
2941 vit != remoteSplit.end(); ++vit)
2943 if(vit->size())
2945 finalPath.push_back(*vit);
2948 kwsys_stl::string relativePath; // result string
2949 // now turn the array of directories into a unix path by puttint /
2950 // between each entry that does not already have one
2951 for(kwsys_stl::vector<String>::iterator vit1 = finalPath.begin();
2952 vit1 != finalPath.end(); ++vit1)
2954 if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
2956 relativePath += "/";
2958 relativePath += *vit1;
2960 return relativePath;
2963 // OK, some fun stuff to get the actual case of a given path.
2964 // Basically, you just need to call ShortPath, then GetLongPathName,
2965 // However, GetLongPathName is not implemented on windows NT and 95,
2966 // so we have to simulate it on those versions
2967 #ifdef _WIN32
2968 int OldWindowsGetLongPath(kwsys_stl::string const& shortPath,
2969 kwsys_stl::string& longPath )
2971 kwsys_stl::string::size_type iFound = shortPath.rfind('/');
2972 if (iFound > 1 && iFound != shortPath.npos)
2974 // recurse to peel off components
2976 if (OldWindowsGetLongPath(shortPath.substr(0, iFound), longPath) > 0)
2978 longPath += '/';
2979 if (shortPath[1] != '/')
2981 WIN32_FIND_DATA findData;
2983 // append the long component name to the path
2985 if (INVALID_HANDLE_VALUE != ::FindFirstFile
2986 (shortPath.c_str(), &findData))
2988 longPath += findData.cFileName;
2990 else
2992 // if FindFirstFile fails, return the error code
2994 longPath = "";
2995 return 0;
3000 else
3002 longPath = shortPath;
3004 return (int)longPath.size();
3008 int PortableGetLongPathName(const char* pathIn,
3009 kwsys_stl::string & longPath)
3011 HMODULE lh = LoadLibrary("Kernel32.dll");
3012 if(lh)
3014 FARPROC proc = GetProcAddress(lh, "GetLongPathNameA");
3015 if(proc)
3017 typedef DWORD (WINAPI * GetLongFunctionPtr) (LPCSTR,LPSTR,DWORD);
3018 GetLongFunctionPtr func = (GetLongFunctionPtr)proc;
3019 char buffer[MAX_PATH+1];
3020 int len = (*func)(pathIn, buffer, MAX_PATH+1);
3021 if(len == 0 || len > MAX_PATH+1)
3023 FreeLibrary(lh);
3024 return 0;
3026 longPath = buffer;
3027 FreeLibrary(lh);
3028 return len;
3030 FreeLibrary(lh);
3032 return OldWindowsGetLongPath(pathIn, longPath);
3034 #endif
3037 //----------------------------------------------------------------------------
3038 kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p)
3040 #ifndef _WIN32
3041 return p;
3042 #else
3043 // Check to see if actual case has already been called
3044 // for this path, and the result is stored in the LongPathMap
3045 SystemToolsTranslationMap::iterator i =
3046 SystemTools::LongPathMap->find(p);
3047 if(i != SystemTools::LongPathMap->end())
3049 return i->second;
3051 kwsys_stl::string shortPath;
3052 if(!SystemTools::GetShortPath(p, shortPath))
3054 return p;
3056 kwsys_stl::string longPath;
3057 int len = PortableGetLongPathName(shortPath.c_str(), longPath);
3058 if(len == 0 || len > MAX_PATH+1)
3060 return p;
3062 // Use original path if conversion back to a long path failed.
3063 if(longPath == shortPath)
3065 longPath = p;
3067 // make sure drive letter is always upper case
3068 if(longPath.size() > 1 && longPath[1] == ':')
3070 longPath[0] = toupper(longPath[0]);
3072 (*SystemTools::LongPathMap)[p] = longPath;
3073 return longPath;
3074 #endif
3077 //----------------------------------------------------------------------------
3078 const char* SystemTools::SplitPathRootComponent(const char* p,
3079 kwsys_stl::string* root)
3081 // Identify the root component.
3082 const char* c = p;
3083 if((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\'))
3085 // Network path.
3086 if(root)
3088 *root = "//";
3090 c += 2;
3092 else if(c[0] == '/')
3094 // Unix path.
3095 if(root)
3097 *root = "/";
3099 c += 1;
3101 else if(c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\'))
3103 // Windows path.
3104 if(root)
3106 (*root) = "_:/";
3107 (*root)[0] = c[0];
3109 c += 3;
3111 else if(c[0] && c[1] == ':')
3113 // Path relative to a windows drive working directory.
3114 if(root)
3116 (*root) = "_:";
3117 (*root)[0] = c[0];
3119 c += 2;
3121 else if(c[0] == '~')
3123 // Home directory. The returned root should always have a
3124 // trailing slash so that appending components as
3125 // c[0]c[1]/c[2]/... works. The remaining path returned should
3126 // skip the first slash if it exists:
3128 // "~" : root = "~/" , return ""
3129 // "~/ : root = "~/" , return ""
3130 // "~/x : root = "~/" , return "x"
3131 // "~u" : root = "~u/", return ""
3132 // "~u/" : root = "~u/", return ""
3133 // "~u/x" : root = "~u/", return "x"
3134 size_t n = 1;
3135 while(c[n] && c[n] != '/')
3137 ++n;
3139 if(root)
3141 root->assign(c, n);
3142 *root += '/';
3144 if(c[n] == '/')
3146 ++n;
3148 c += n;
3150 else
3152 // Relative path.
3153 if(root)
3155 *root = "";
3159 // Return the remaining path.
3160 return c;
3163 //----------------------------------------------------------------------------
3164 void SystemTools::SplitPath(const char* p,
3165 kwsys_stl::vector<kwsys_stl::string>& components,
3166 bool expand_home_dir)
3168 const char* c = p;
3169 components.clear();
3171 // Identify the root component.
3173 kwsys_stl::string root;
3174 c = SystemTools::SplitPathRootComponent(c, &root);
3176 // Expand home directory references if requested.
3177 if(expand_home_dir && !root.empty() && root[0] == '~')
3179 kwsys_stl::string homedir;
3180 root = root.substr(0, root.size()-1);
3181 if(root.size() == 1)
3183 #if defined(_WIN32) && !defined(__CYGWIN__)
3184 if(const char* userp = getenv("USERPROFILE"))
3186 homedir = userp;
3188 else
3189 #endif
3190 if(const char* h = getenv("HOME"))
3192 homedir = h;
3195 #ifdef HAVE_GETPWNAM
3196 else if(passwd* pw = getpwnam(root.c_str()+1))
3198 if(pw->pw_dir)
3200 homedir = pw->pw_dir;
3203 #endif
3204 if(!homedir.empty() && (homedir[homedir.size()-1] == '/' ||
3205 homedir[homedir.size()-1] == '\\'))
3207 homedir = homedir.substr(0, homedir.size()-1);
3209 SystemTools::SplitPath(homedir.c_str(), components);
3211 else
3213 components.push_back(root);
3217 // Parse the remaining components.
3218 const char* first = c;
3219 const char* last = first;
3220 for(;*last; ++last)
3222 if(*last == '/' || *last == '\\')
3224 // End of a component. Save it.
3225 components.push_back(
3226 kwsys_stl::string(first,static_cast<kwsys_stl::string::size_type>(
3227 last-first)));
3228 first = last+1;
3232 // Save the last component unless there were no components.
3233 if(last != c)
3235 components.push_back(
3236 kwsys_stl::string(first,static_cast<kwsys_stl::string::size_type>(
3237 last-first)));
3241 //----------------------------------------------------------------------------
3242 kwsys_stl::string
3243 SystemTools::JoinPath(const kwsys_stl::vector<kwsys_stl::string>& components)
3245 return SystemTools::JoinPath(components.begin(), components.end());
3248 //----------------------------------------------------------------------------
3249 kwsys_stl::string
3250 SystemTools
3251 ::JoinPath(kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
3252 kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
3254 // Construct result in a single string.
3255 kwsys_stl::string result;
3257 // The first two components do not add a slash.
3258 if(first != last)
3260 result += *first++;
3262 if(first != last)
3264 result += *first++;
3267 // All remaining components are always separated with a slash.
3268 while(first != last)
3270 result += "/";
3271 result += *first++;
3274 // Return the concatenated result.
3275 return result;
3278 //----------------------------------------------------------------------------
3279 bool SystemTools::ComparePath(const char* c1, const char* c2)
3281 #if defined(_WIN32) || defined(__APPLE__)
3282 # ifdef _MSC_VER
3283 return _stricmp(c1, c2) == 0;
3284 # elif defined(__APPLE__) || defined(__GNUC__)
3285 return strcasecmp(c1, c2) == 0;
3286 #else
3287 return SystemTools::Strucmp(c1, c2) == 0;
3288 # endif
3289 #else
3290 return strcmp(c1, c2) == 0;
3291 #endif
3294 //----------------------------------------------------------------------------
3295 bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines, char separator)
3297 kwsys_stl::string data(str);
3298 kwsys_stl::string::size_type lpos = 0;
3299 while(lpos < data.length())
3301 kwsys_stl::string::size_type rpos = data.find_first_of(separator, lpos);
3302 if(rpos == kwsys_stl::string::npos)
3304 // Line ends at end of string without a newline.
3305 lines.push_back(data.substr(lpos));
3306 return false;
3308 else
3310 // Line ends in a "\n", remove the character.
3311 lines.push_back(data.substr(lpos, rpos-lpos));
3313 lpos = rpos+1;
3315 return true;
3318 //----------------------------------------------------------------------------
3319 bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines)
3321 kwsys_stl::string data(str);
3322 kwsys_stl::string::size_type lpos = 0;
3323 while(lpos < data.length())
3325 kwsys_stl::string::size_type rpos = data.find_first_of("\n", lpos);
3326 if(rpos == kwsys_stl::string::npos)
3328 // Line ends at end of string without a newline.
3329 lines.push_back(data.substr(lpos));
3330 return false;
3332 if((rpos > lpos) && (data[rpos-1] == '\r'))
3334 // Line ends in a "\r\n" pair, remove both characters.
3335 lines.push_back(data.substr(lpos, (rpos-1)-lpos));
3337 else
3339 // Line ends in a "\n", remove the character.
3340 lines.push_back(data.substr(lpos, rpos-lpos));
3342 lpos = rpos+1;
3344 return true;
3348 * Return path of a full filename (no trailing slashes).
3349 * Warning: returned path is converted to Unix slashes format.
3351 kwsys_stl::string SystemTools::GetFilenamePath(const kwsys_stl::string& filename)
3353 kwsys_stl::string fn = filename;
3354 SystemTools::ConvertToUnixSlashes(fn);
3356 kwsys_stl::string::size_type slash_pos = fn.rfind("/");
3357 if(slash_pos != kwsys_stl::string::npos)
3359 kwsys_stl::string ret = fn.substr(0, slash_pos);
3360 if(ret.size() == 2 && ret[1] == ':')
3362 return ret + '/';
3364 if(ret.size() == 0)
3366 return "/";
3368 return ret;
3370 else
3372 return "";
3378 * Return file name of a full filename (i.e. file name without path).
3380 kwsys_stl::string SystemTools::GetFilenameName(const kwsys_stl::string& filename)
3382 #if defined(_WIN32)
3383 kwsys_stl::string::size_type slash_pos = filename.find_last_of("/\\");
3384 #else
3385 kwsys_stl::string::size_type slash_pos = filename.find_last_of("/");
3386 #endif
3387 if(slash_pos != kwsys_stl::string::npos)
3389 return filename.substr(slash_pos + 1);
3391 else
3393 return filename;
3399 * Return file extension of a full filename (dot included).
3400 * Warning: this is the longest extension (for example: .tar.gz)
3402 kwsys_stl::string SystemTools::GetFilenameExtension(const kwsys_stl::string& filename)
3404 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3405 kwsys_stl::string::size_type dot_pos = name.find(".");
3406 if(dot_pos != kwsys_stl::string::npos)
3408 return name.substr(dot_pos);
3410 else
3412 return "";
3417 * Return file extension of a full filename (dot included).
3418 * Warning: this is the shortest extension (for example: .gz of .tar.gz)
3420 kwsys_stl::string SystemTools::GetFilenameLastExtension(const kwsys_stl::string& filename)
3422 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3423 kwsys_stl::string::size_type dot_pos = name.rfind(".");
3424 if(dot_pos != kwsys_stl::string::npos)
3426 return name.substr(dot_pos);
3428 else
3430 return "";
3435 * Return file name without extension of a full filename (i.e. without path).
3436 * Warning: it considers the longest extension (for example: .tar.gz)
3438 kwsys_stl::string SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string& filename)
3440 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3441 kwsys_stl::string::size_type dot_pos = name.find(".");
3442 if(dot_pos != kwsys_stl::string::npos)
3444 return name.substr(0, dot_pos);
3446 else
3448 return name;
3454 * Return file name without extension of a full filename (i.e. without path).
3455 * Warning: it considers the last extension (for example: removes .gz
3456 * from .tar.gz)
3458 kwsys_stl::string
3459 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string& filename)
3461 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3462 kwsys_stl::string::size_type dot_pos = name.rfind(".");
3463 if(dot_pos != kwsys_stl::string::npos)
3465 return name.substr(0, dot_pos);
3467 else
3469 return name;
3473 bool SystemTools::FileHasSignature(const char *filename,
3474 const char *signature,
3475 long offset)
3477 if (!filename || !signature)
3479 return false;
3482 FILE *fp;
3483 fp = fopen(filename, "rb");
3484 if (!fp)
3486 return false;
3489 fseek(fp, offset, SEEK_SET);
3491 bool res = false;
3492 size_t signature_len = strlen(signature);
3493 char *buffer = new char [signature_len];
3495 if (fread(buffer, 1, signature_len, fp) == signature_len)
3497 res = (!strncmp(buffer, signature, signature_len) ? true : false);
3500 delete [] buffer;
3502 fclose(fp);
3503 return res;
3506 SystemTools::FileTypeEnum
3507 SystemTools::DetectFileType(const char *filename,
3508 unsigned long length,
3509 double percent_bin)
3511 if (!filename || percent_bin < 0)
3513 return SystemTools::FileTypeUnknown;
3516 FILE *fp;
3517 fp = fopen(filename, "rb");
3518 if (!fp)
3520 return SystemTools::FileTypeUnknown;
3523 // Allocate buffer and read bytes
3525 unsigned char *buffer = new unsigned char [length];
3526 size_t read_length = fread(buffer, 1, length, fp);
3527 fclose(fp);
3528 if (read_length == 0)
3530 return SystemTools::FileTypeUnknown;
3533 // Loop over contents and count
3535 size_t text_count = 0;
3537 const unsigned char *ptr = buffer;
3538 const unsigned char *buffer_end = buffer + read_length;
3540 while (ptr != buffer_end)
3542 if ((*ptr >= 0x20 && *ptr <= 0x7F) ||
3543 *ptr == '\n' ||
3544 *ptr == '\r' ||
3545 *ptr == '\t')
3547 text_count++;
3549 ptr++;
3552 delete [] buffer;
3554 double current_percent_bin =
3555 (static_cast<double>(read_length - text_count) /
3556 static_cast<double>(read_length));
3558 if (current_percent_bin >= percent_bin)
3560 return SystemTools::FileTypeBinary;
3563 return SystemTools::FileTypeText;
3566 bool SystemTools::LocateFileInDir(const char *filename,
3567 const char *dir,
3568 kwsys_stl::string& filename_found,
3569 int try_filename_dirs)
3571 if (!filename || !dir)
3573 return false;
3576 // Get the basename of 'filename'
3578 kwsys_stl::string filename_base = SystemTools::GetFilenameName(filename);
3580 // Check if 'dir' is really a directory
3581 // If win32 and matches something like C:, accept it as a dir
3583 kwsys_stl::string real_dir;
3584 if (!SystemTools::FileIsDirectory(dir))
3586 #if defined( _WIN32 )
3587 size_t dir_len = strlen(dir);
3588 if (dir_len < 2 || dir[dir_len - 1] != ':')
3590 #endif
3591 real_dir = SystemTools::GetFilenamePath(dir);
3592 dir = real_dir.c_str();
3593 #if defined( _WIN32 )
3595 #endif
3598 // Try to find the file in 'dir'
3600 bool res = false;
3601 if (filename_base.size() && dir)
3603 size_t dir_len = strlen(dir);
3604 int need_slash =
3605 (dir_len && dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\');
3607 kwsys_stl::string temp = dir;
3608 if (need_slash)
3610 temp += "/";
3612 temp += filename_base;
3614 if (SystemTools::FileExists(temp.c_str()))
3616 res = true;
3617 filename_found = temp;
3620 // If not found, we can try harder by appending part of the file to
3621 // to the directory to look inside.
3622 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
3623 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
3625 else if (try_filename_dirs)
3627 kwsys_stl::string filename_dir(filename);
3628 kwsys_stl::string filename_dir_base;
3629 kwsys_stl::string filename_dir_bases;
3632 filename_dir = SystemTools::GetFilenamePath(filename_dir);
3633 filename_dir_base = SystemTools::GetFilenameName(filename_dir);
3634 #if defined( _WIN32 )
3635 if (!filename_dir_base.size() ||
3636 filename_dir_base[filename_dir_base.size() - 1] == ':')
3637 #else
3638 if (!filename_dir_base.size())
3639 #endif
3641 break;
3644 filename_dir_bases = filename_dir_base + "/" + filename_dir_bases;
3646 temp = dir;
3647 if (need_slash)
3649 temp += "/";
3651 temp += filename_dir_bases;
3653 res = SystemTools::LocateFileInDir(
3654 filename_base.c_str(), temp.c_str(), filename_found, 0);
3656 } while (!res && filename_dir_base.size());
3660 return res;
3663 bool SystemTools::FileIsFullPath(const char* in_name)
3665 kwsys_stl::string name = in_name;
3666 #if defined(_WIN32) || defined(__CYGWIN__)
3667 // On Windows, the name must be at least two characters long.
3668 if(name.length() < 2)
3670 return false;
3672 if(name[1] == ':')
3674 return true;
3676 if(name[0] == '\\')
3678 return true;
3680 #else
3681 // On UNIX, the name must be at least one character long.
3682 if(name.length() < 1)
3684 return false;
3686 #endif
3687 #if !defined(_WIN32)
3688 if(name[0] == '~')
3690 return true;
3692 #endif
3693 // On UNIX, the name must begin in a '/'.
3694 // On Windows, if the name begins in a '/', then it is a full
3695 // network path.
3696 if(name[0] == '/')
3698 return true;
3700 return false;
3703 bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
3705 #if defined(WIN32) && !defined(__CYGWIN__)
3706 const int size = int(strlen(path)) +1; // size of return
3707 char *buffer = new char[size]; // create a buffer
3708 char *tempPath = new char[size]; // create a buffer
3709 int ret;
3711 // if the path passed in has quotes around it, first remove the quotes
3712 if (path[0] == '"' && path[strlen(path)-1] == '"')
3714 strcpy(tempPath,path+1);
3715 tempPath[strlen(tempPath)-1] = '\0';
3717 else
3719 strcpy(tempPath,path);
3722 buffer[0] = 0;
3723 ret = GetShortPathName(tempPath, buffer, size);
3725 if(buffer[0] == 0 || ret > size)
3727 delete [] buffer;
3728 delete [] tempPath;
3729 return false;
3731 else
3733 shortPath = buffer;
3734 delete [] buffer;
3735 delete [] tempPath;
3736 return true;
3738 #else
3739 shortPath = path;
3740 return true;
3741 #endif
3744 void SystemTools::SplitProgramFromArgs(const char* path,
3745 kwsys_stl::string& program, kwsys_stl::string& args)
3747 // see if this is a full path to a program
3748 // if so then set program to path and args to nothing
3749 if(SystemTools::FileExists(path))
3751 program = path;
3752 args = "";
3753 return;
3755 // Try to find the program in the path, note the program
3756 // may have spaces in its name so we have to look for it
3757 kwsys_stl::vector<kwsys_stl::string> e;
3758 kwsys_stl::string findProg = SystemTools::FindProgram(path, e);
3759 if(findProg.size())
3761 program = findProg;
3762 args = "";
3763 return;
3766 // Now try and peel off space separated chunks from the end of the string
3767 // so the largest path possible is found allowing for spaces in the path
3768 kwsys_stl::string dir = path;
3769 kwsys_stl::string::size_type spacePos = dir.rfind(' ');
3770 while(spacePos != kwsys_stl::string::npos)
3772 kwsys_stl::string tryProg = dir.substr(0, spacePos);
3773 // See if the file exists
3774 if(SystemTools::FileExists(tryProg.c_str()))
3776 program = tryProg;
3777 // remove trailing spaces from program
3778 kwsys_stl::string::size_type pos = program.size()-1;
3779 while(program[pos] == ' ')
3781 program.erase(pos);
3782 pos--;
3784 args = dir.substr(spacePos, dir.size()-spacePos);
3785 return;
3787 // Now try and find the the program in the path
3788 findProg = SystemTools::FindProgram(tryProg.c_str(), e);
3789 if(findProg.size())
3791 program = findProg;
3792 // remove trailing spaces from program
3793 kwsys_stl::string::size_type pos = program.size()-1;
3794 while(program[pos] == ' ')
3796 program.erase(pos);
3797 pos--;
3799 args = dir.substr(spacePos, dir.size()-spacePos);
3800 return;
3802 // move past the space for the next search
3803 spacePos--;
3804 spacePos = dir.rfind(' ', spacePos);
3807 program = "";
3808 args = "";
3811 kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format)
3813 char buf[1024];
3814 time_t t;
3815 time(&t);
3816 strftime(buf, sizeof(buf), format, localtime(&t));
3817 return kwsys_stl::string(buf);
3820 kwsys_stl::string SystemTools::MakeCindentifier(const char* s)
3822 kwsys_stl::string str(s);
3823 if (str.find_first_of("0123456789") == 0)
3825 str = "_" + str;
3828 kwsys_stl::string permited_chars("_"
3829 "abcdefghijklmnopqrstuvwxyz"
3830 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3831 "0123456789");
3832 kwsys_stl::string::size_type pos = 0;
3833 while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_stl::string::npos)
3835 str[pos] = '_';
3837 return str;
3840 // Due to a buggy stream library on the HP and another on Mac OS X, we
3841 // need this very carefully written version of getline. Returns true
3842 // if any data were read before the end-of-file was reached.
3843 bool SystemTools::GetLineFromStream(kwsys_ios::istream& is,
3844 kwsys_stl::string& line,
3845 bool* has_newline /* = 0 */,
3846 long sizeLimit /* = -1 */)
3848 const int bufferSize = 1024;
3849 char buffer[bufferSize];
3850 bool haveData = false;
3851 bool haveNewline = false;
3853 // Start with an empty line.
3854 line = "";
3856 long leftToRead = sizeLimit;
3858 // If no characters are read from the stream, the end of file has
3859 // been reached. Clear the fail bit just before reading.
3860 while(!haveNewline &&
3861 leftToRead != 0 &&
3862 (is.clear(is.rdstate() & ~kwsys_ios::ios::failbit),
3863 is.getline(buffer, bufferSize), is.gcount() > 0))
3865 // We have read at least one byte.
3866 haveData = true;
3868 // If newline character was read the gcount includes the character
3869 // but the buffer does not: the end of line has been reached.
3870 size_t length = strlen(buffer);
3871 if(length < static_cast<size_t>(is.gcount()))
3873 haveNewline = true;
3876 // Avoid storing a carriage return character.
3877 if(length > 0 && buffer[length-1] == '\r')
3879 buffer[length-1] = 0;
3882 // if we read too much then truncate the buffer
3883 if (leftToRead > 0)
3885 if (static_cast<long>(length) > leftToRead)
3887 buffer[leftToRead-1] = 0;
3888 leftToRead = 0;
3890 else
3892 leftToRead -= static_cast<long>(length);
3896 // Append the data read to the line.
3897 line.append(buffer);
3898 sizeLimit = sizeLimit - static_cast<long>(length);
3901 // Return the results.
3902 if(has_newline)
3904 *has_newline = haveNewline;
3906 return haveData;
3909 int SystemTools::GetTerminalWidth()
3911 int width = -1;
3912 #ifdef HAVE_TTY_INFO
3913 struct winsize ws;
3914 char *columns; /* Unix98 environment variable */
3915 if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0)
3917 width = ws.ws_col;
3919 if(!isatty(STDOUT_FILENO))
3921 width = -1;
3923 columns = getenv("COLUMNS");
3924 if(columns && *columns)
3926 long t;
3927 char *endptr;
3928 t = strtol(columns, &endptr, 0);
3929 if(endptr && !*endptr && (t>0) && (t<1000))
3931 width = static_cast<int>(t);
3934 if ( width < 9 )
3936 width = -1;
3938 #endif
3939 return width;
3942 bool SystemTools::GetPermissions(const char* file, mode_t& mode)
3944 if ( !file )
3946 return false;
3949 struct stat st;
3950 if ( stat(file, &st) < 0 )
3952 return false;
3954 mode = st.st_mode;
3955 return true;
3958 bool SystemTools::SetPermissions(const char* file, mode_t mode)
3960 if ( !file )
3962 return false;
3964 if ( !SystemTools::FileExists(file) )
3966 return false;
3968 if ( chmod(file, mode) < 0 )
3970 return false;
3973 return true;
3976 kwsys_stl::string SystemTools::GetParentDirectory(const char* fileOrDir)
3978 if ( !fileOrDir || !*fileOrDir )
3980 return "";
3982 kwsys_stl::string res = fileOrDir;
3983 SystemTools::ConvertToUnixSlashes(res);
3984 kwsys_stl::string::size_type cc = res.size()-1;
3985 if ( res[cc] == '/' )
3987 cc --;
3989 for ( ; cc > 0; cc -- )
3991 if ( res[cc] == '/' )
3993 break;
3996 return res.substr(0, cc);
3999 bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir)
4001 kwsys_stl::string subdir = cSubdir;
4002 kwsys_stl::string dir = cDir;
4003 SystemTools::ConvertToUnixSlashes(dir);
4004 kwsys_stl::string path = subdir;
4007 path = SystemTools::GetParentDirectory(path.c_str());
4008 if(SystemTools::ComparePath(dir.c_str(), path.c_str()))
4010 return true;
4013 while ( path.size() > dir.size() );
4014 return false;
4017 kwsys_stl::string SystemTools::FileExistsInParentDirectories(const char* fname,
4018 const char* directory, const char* toplevel)
4020 kwsys_stl::string file = fname;
4021 SystemTools::ConvertToUnixSlashes(file);
4022 kwsys_stl::string dir = directory;
4023 SystemTools::ConvertToUnixSlashes(dir);
4024 while ( !dir.empty() )
4026 kwsys_stl::string path = dir + "/" + file;
4027 if ( SystemTools::FileExists(path.c_str()) )
4029 return path;
4031 if ( dir.size() < strlen(toplevel) )
4033 break;
4035 dir = SystemTools::GetParentDirectory(dir.c_str());
4037 return "";
4040 void SystemTools::Delay(unsigned int msec)
4042 #ifdef _WIN32
4043 Sleep(msec);
4044 #else
4045 // The sleep function gives 1 second resolution and the usleep
4046 // function gives 1e-6 second resolution but on some platforms has a
4047 // maximum sleep time of 1 second. This could be re-implemented to
4048 // use select with masked signals or pselect to mask signals
4049 // atomically. If select is given empty sets and zero as the max
4050 // file descriptor but a non-zero timeout it can be used to block
4051 // for a precise amount of time.
4052 if(msec >= 1000)
4054 sleep(msec / 1000);
4055 usleep((msec % 1000) * 1000);
4057 else
4059 usleep(msec * 1000);
4061 #endif
4064 void SystemTools::ConvertWindowsCommandLineToUnixArguments(
4065 const char *cmd_line, int *argc, char ***argv)
4067 if (!cmd_line || !argc || !argv)
4069 return;
4072 // A space delimites an argument except when it is inside a quote
4074 (*argc) = 1;
4076 size_t cmd_line_len = strlen(cmd_line);
4078 size_t i;
4079 for (i = 0; i < cmd_line_len; i++)
4081 while (isspace(cmd_line[i]) && i < cmd_line_len)
4083 i++;
4085 if (i < cmd_line_len)
4087 if (cmd_line[i] == '\"')
4089 i++;
4090 while (cmd_line[i] != '\"' && i < cmd_line_len)
4092 i++;
4094 (*argc)++;
4096 else
4098 while (!isspace(cmd_line[i]) && i < cmd_line_len)
4100 i++;
4102 (*argc)++;
4107 (*argv) = new char* [(*argc) + 1];
4108 (*argv)[(*argc)] = NULL;
4110 // Set the first arg to be the exec name
4112 (*argv)[0] = new char [1024];
4113 #ifdef _WIN32
4114 ::GetModuleFileName(0, (*argv)[0], 1024);
4115 #else
4116 (*argv)[0][0] = '\0';
4117 #endif
4119 // Allocate the others
4121 int j;
4122 for (j = 1; j < (*argc); j++)
4124 (*argv)[j] = new char [cmd_line_len + 10];
4127 // Grab the args
4129 size_t pos;
4130 int argc_idx = 1;
4132 for (i = 0; i < cmd_line_len; i++)
4134 while (isspace(cmd_line[i]) && i < cmd_line_len)
4136 i++;
4138 if (i < cmd_line_len)
4140 if (cmd_line[i] == '\"')
4142 i++;
4143 pos = i;
4144 while (cmd_line[i] != '\"' && i < cmd_line_len)
4146 i++;
4148 memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
4149 (*argv)[argc_idx][i - pos] = '\0';
4150 argc_idx++;
4152 else
4154 pos = i;
4155 while (!isspace(cmd_line[i]) && i < cmd_line_len)
4157 i++;
4159 memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
4160 (*argv)[argc_idx][i - pos] = '\0';
4161 argc_idx++;
4167 kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
4169 kwsys_stl::string res;
4171 #ifdef _WIN32
4172 char buffer[256];
4174 OSVERSIONINFOEX osvi;
4175 BOOL bOsVersionInfoEx;
4177 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
4178 // If that fails, try using the OSVERSIONINFO structure.
4180 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
4181 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
4183 bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
4184 if (!bOsVersionInfoEx)
4186 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
4187 if (!GetVersionEx((OSVERSIONINFO *)&osvi))
4189 return 0;
4193 switch (osvi.dwPlatformId)
4195 // Test for the Windows NT product family.
4197 case VER_PLATFORM_WIN32_NT:
4199 // Test for the specific product family.
4201 if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
4203 #if (_MSC_VER >= 1300)
4204 if (osvi.wProductType == VER_NT_WORKSTATION)
4206 res += "Microsoft Windows Vista";
4208 else
4210 res += "Microsoft Windows Server 2008 family";
4212 #else
4213 res += "Microsoft Windows Vista or Windows Server 2008";
4214 #endif
4217 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
4219 res += "Microsoft Windows Server 2003 family";
4222 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
4224 res += "Microsoft Windows XP";
4227 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
4229 res += "Microsoft Windows 2000";
4232 if (osvi.dwMajorVersion <= 4)
4234 res += "Microsoft Windows NT";
4237 // Test for specific product on Windows NT 4.0 SP6 and later.
4239 if (bOsVersionInfoEx)
4241 // Test for the workstation type.
4243 #if (_MSC_VER >= 1300)
4244 if (osvi.wProductType == VER_NT_WORKSTATION)
4246 if (osvi.dwMajorVersion == 4)
4248 res += " Workstation 4.0";
4250 else if (osvi.dwMajorVersion == 5)
4252 if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
4254 res += " Home Edition";
4256 else
4258 res += " Professional";
4263 // Test for the server type.
4265 else if (osvi.wProductType == VER_NT_SERVER)
4267 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
4269 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
4271 res += " Datacenter Edition";
4273 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4275 res += " Enterprise Edition";
4277 else if (osvi.wSuiteMask == VER_SUITE_BLADE)
4279 res += " Web Edition";
4281 else
4283 res += " Standard Edition";
4287 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
4289 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
4291 res += " Datacenter Server";
4293 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4295 res += " Advanced Server";
4297 else
4299 res += " Server";
4303 else if (osvi.dwMajorVersion <= 4) // Windows NT 4.0
4305 if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4307 res += " Server 4.0, Enterprise Edition";
4309 else
4311 res += " Server 4.0";
4315 #endif // Visual Studio 7 and up
4318 // Test for specific product on Windows NT 4.0 SP5 and earlier
4320 else
4322 HKEY hKey;
4323 #define BUFSIZE 80
4324 char szProductType[BUFSIZE];
4325 DWORD dwBufLen=BUFSIZE;
4326 LONG lRet;
4328 lRet = RegOpenKeyEx(
4329 HKEY_LOCAL_MACHINE,
4330 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
4331 0, KEY_QUERY_VALUE, &hKey);
4332 if (lRet != ERROR_SUCCESS)
4334 return 0;
4337 lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL,
4338 (LPBYTE) szProductType, &dwBufLen);
4340 if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
4342 return 0;
4345 RegCloseKey(hKey);
4347 if (lstrcmpi("WINNT", szProductType) == 0)
4349 res += " Workstation";
4351 if (lstrcmpi("LANMANNT", szProductType) == 0)
4353 res += " Server";
4355 if (lstrcmpi("SERVERNT", szProductType) == 0)
4357 res += " Advanced Server";
4360 res += " ";
4361 sprintf(buffer, "%ld", osvi.dwMajorVersion);
4362 res += buffer;
4363 res += ".";
4364 sprintf(buffer, "%ld", osvi.dwMinorVersion);
4365 res += buffer;
4368 // Display service pack (if any) and build number.
4370 if (osvi.dwMajorVersion == 4 &&
4371 lstrcmpi(osvi.szCSDVersion, "Service Pack 6") == 0)
4373 HKEY hKey;
4374 LONG lRet;
4376 // Test for SP6 versus SP6a.
4378 lRet = RegOpenKeyEx(
4379 HKEY_LOCAL_MACHINE,
4380 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
4381 0, KEY_QUERY_VALUE, &hKey);
4383 if (lRet == ERROR_SUCCESS)
4385 res += " Service Pack 6a (Build ";
4386 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4387 res += buffer;
4388 res += ")";
4390 else // Windows NT 4.0 prior to SP6a
4392 res += " ";
4393 res += osvi.szCSDVersion;
4394 res += " (Build ";
4395 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4396 res += buffer;
4397 res += ")";
4400 RegCloseKey(hKey);
4402 else // Windows NT 3.51 and earlier or Windows 2000 and later
4404 res += " ";
4405 res += osvi.szCSDVersion;
4406 res += " (Build ";
4407 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4408 res += buffer;
4409 res += ")";
4412 break;
4414 // Test for the Windows 95 product family.
4416 case VER_PLATFORM_WIN32_WINDOWS:
4418 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
4420 res += "Microsoft Windows 95";
4421 if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
4423 res += " OSR2";
4427 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
4429 res += "Microsoft Windows 98";
4430 if (osvi.szCSDVersion[1] == 'A')
4432 res += " SE";
4436 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
4438 res += "Microsoft Windows Millennium Edition";
4440 break;
4442 case VER_PLATFORM_WIN32s:
4444 res += "Microsoft Win32s";
4445 break;
4447 #endif
4449 return res;
4452 // ----------------------------------------------------------------------
4453 bool SystemTools::ParseURLProtocol( const kwsys_stl::string& URL,
4454 kwsys_stl::string& protocol,
4455 kwsys_stl::string& dataglom )
4457 // match 0 entire url
4458 // match 1 protocol
4459 // match 2 dataglom following protocol://
4460 kwsys::RegularExpression urlRe( VTK_URL_PROTOCOL_REGEX );
4462 if ( ! urlRe.find( URL ) ) return false;
4464 protocol = urlRe.match( 1 );
4465 dataglom = urlRe.match( 2 );
4467 return true;
4470 // ----------------------------------------------------------------------
4471 bool SystemTools::ParseURL( const kwsys_stl::string& URL,
4472 kwsys_stl::string& protocol,
4473 kwsys_stl::string& username,
4474 kwsys_stl::string& password,
4475 kwsys_stl::string& hostname,
4476 kwsys_stl::string& dataport,
4477 kwsys_stl::string& database )
4479 kwsys::RegularExpression urlRe( VTK_URL_REGEX );
4480 if ( ! urlRe.find( URL ) ) return false;
4482 // match 0 URL
4483 // match 1 protocol
4484 // match 2 mangled user
4485 // match 3 username
4486 // match 4 mangled password
4487 // match 5 password
4488 // match 6 hostname
4489 // match 7 mangled port
4490 // match 8 dataport
4491 // match 9 database name
4493 protocol = urlRe.match( 1 );
4494 username = urlRe.match( 3 );
4495 password = urlRe.match( 5 );
4496 hostname = urlRe.match( 6 );
4497 dataport = urlRe.match( 8 );
4498 database = urlRe.match( 9 );
4500 return true;
4503 // ----------------------------------------------------------------------
4504 // These must NOT be initialized. Default initialization to zero is
4505 // necessary.
4506 unsigned int SystemToolsManagerCount;
4507 SystemToolsTranslationMap *SystemTools::TranslationMap;
4508 SystemToolsTranslationMap *SystemTools::LongPathMap;
4510 // SystemToolsManager manages the SystemTools singleton.
4511 // SystemToolsManager should be included in any translation unit
4512 // that will use SystemTools or that implements the singleton
4513 // pattern. It makes sure that the SystemTools singleton is created
4514 // before and destroyed after all other singletons in CMake.
4516 SystemToolsManager::SystemToolsManager()
4518 if(++SystemToolsManagerCount == 1)
4520 SystemTools::ClassInitialize();
4524 SystemToolsManager::~SystemToolsManager()
4526 if(--SystemToolsManagerCount == 0)
4528 SystemTools::ClassFinalize();
4532 void SystemTools::ClassInitialize()
4534 // Allocate the translation map first.
4535 SystemTools::TranslationMap = new SystemToolsTranslationMap;
4536 SystemTools::LongPathMap = new SystemToolsTranslationMap;
4538 // Add some special translation paths for unix. These are not added
4539 // for windows because drive letters need to be maintained. Also,
4540 // there are not sym-links and mount points on windows anyway.
4541 #if !defined(_WIN32) || defined(__CYGWIN__)
4542 // Work-around an SGI problem by always adding this mapping:
4543 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
4544 // The tmp path is frequently a logical path so always keep it:
4545 SystemTools::AddKeepPath("/tmp/");
4547 // If the current working directory is a logical path then keep the
4548 // logical name.
4549 if(const char* pwd = getenv("PWD"))
4551 char buf[2048];
4552 if(const char* cwd = Getcwd(buf, 2048))
4554 // The current working directory may be a logical path. Find
4555 // the shortest logical path that still produces the correct
4556 // physical path.
4557 kwsys_stl::string cwd_changed;
4558 kwsys_stl::string pwd_changed;
4560 // Test progressively shorter logical-to-physical mappings.
4561 kwsys_stl::string pwd_str = pwd;
4562 kwsys_stl::string cwd_str = cwd;
4563 kwsys_stl::string pwd_path;
4564 Realpath(pwd, pwd_path);
4565 while(cwd_str == pwd_path && cwd_str != pwd_str)
4567 // The current pair of paths is a working logical mapping.
4568 cwd_changed = cwd_str;
4569 pwd_changed = pwd_str;
4571 // Strip off one directory level and see if the logical
4572 // mapping still works.
4573 pwd_str = SystemTools::GetFilenamePath(pwd_str.c_str());
4574 cwd_str = SystemTools::GetFilenamePath(cwd_str.c_str());
4575 Realpath(pwd_str.c_str(), pwd_path);
4578 // Add the translation to keep the logical path name.
4579 if(!cwd_changed.empty() && !pwd_changed.empty())
4581 SystemTools::AddTranslationPath(cwd_changed.c_str(),
4582 pwd_changed.c_str());
4586 #endif
4589 void SystemTools::ClassFinalize()
4591 delete SystemTools::TranslationMap;
4592 delete SystemTools::LongPathMap;
4596 } // namespace KWSYS_NAMESPACE
4598 #if defined(_MSC_VER) && defined(_DEBUG)
4599 # include <crtdbg.h>
4600 # include <stdio.h>
4601 # include <stdlib.h>
4602 namespace KWSYS_NAMESPACE
4605 static int SystemToolsDebugReport(int, char* message, int*)
4607 fprintf(stderr, "%s", message);
4608 fflush(stderr);
4609 return 1; // no further reporting required
4612 void SystemTools::EnableMSVCDebugHook()
4614 if (getenv("DART_TEST_FROM_DART"))
4616 _CrtSetReportHook(SystemToolsDebugReport);
4620 } // namespace KWSYS_NAMESPACE
4621 #else
4622 namespace KWSYS_NAMESPACE
4624 void SystemTools::EnableMSVCDebugHook() {}
4625 } // namespace KWSYS_NAMESPACE
4626 #endif