ENH: fix for VS6 and Cygwin
[cmake.git] / Source / kwsys / SystemTools.cxx
blob8d7ebfa6c514503add58a34de4c2f26193156f4d
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);
209 #else
210 #include <sys/types.h>
211 #include <fcntl.h>
212 #include <unistd.h>
213 inline int Mkdir(const char* dir)
215 return mkdir(dir, 00777);
217 inline int Rmdir(const char* dir)
219 return rmdir(dir);
221 inline const char* Getcwd(char* buf, unsigned int len)
223 const char* ret = getcwd(buf, len);
224 if(!ret)
226 fprintf(stderr, "No current working directory\n");
227 abort();
229 return ret;
232 inline int Chdir(const char* dir)
234 return chdir(dir);
236 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
238 char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
240 realpath(path, resolved_name);
241 resolved_path = resolved_name;
243 #endif
245 #if !defined(_WIN32) && defined(__COMO__)
246 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
247 extern "C"
249 extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
250 extern int pclose (FILE *__stream) __THROW;
251 extern char *realpath (__const char *__restrict __name,
252 char *__restrict __resolved) __THROW;
253 extern char *strdup (__const char *__s) __THROW;
254 extern int putenv (char *__string) __THROW;
256 #endif
258 /* Implement floattime() for various platforms */
259 // Taken from Python 2.1.3
261 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
262 # include <sys/timeb.h>
263 # define HAVE_FTIME
264 # if defined( __BORLANDC__)
265 # define FTIME ftime
266 # define TIMEB timeb
267 # else // Visual studio?
268 # define FTIME _ftime
269 # define TIMEB _timeb
270 # endif
271 #elif defined( __CYGWIN__ ) || defined( __linux__ )
272 # include <sys/time.h>
273 # include <time.h>
274 # define HAVE_GETTIMEOFDAY
275 #endif
277 namespace KWSYS_NAMESPACE
280 class SystemToolsTranslationMap :
281 public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
286 double
287 SystemTools::GetTime(void)
289 /* There are three ways to get the time:
290 (1) gettimeofday() -- resolution in microseconds
291 (2) ftime() -- resolution in milliseconds
292 (3) time() -- resolution in seconds
293 In all cases the return value is a float in seconds.
294 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
295 fail, so we fall back on ftime() or time().
296 Note: clock resolution does not imply clock accuracy! */
297 #ifdef HAVE_GETTIMEOFDAY
299 struct timeval t;
300 #ifdef GETTIMEOFDAY_NO_TZ
301 if (gettimeofday(&t) == 0)
302 return static_cast<double>(t.tv_sec) + t.tv_usec*0.000001;
303 #else /* !GETTIMEOFDAY_NO_TZ */
304 if (gettimeofday(&t, static_cast<struct timezone *>(NULL)) == 0)
305 return static_cast<double>(t.tv_sec) + t.tv_usec*0.000001;
306 #endif /* !GETTIMEOFDAY_NO_TZ */
308 #endif /* !HAVE_GETTIMEOFDAY */
310 #if defined(HAVE_FTIME)
311 struct TIMEB t;
312 ::FTIME(&t);
313 return static_cast<double>(t.time) +
314 static_cast<double>(t.millitm) * static_cast<double>(0.001);
315 #else /* !HAVE_FTIME */
316 time_t secs;
317 time(&secs);
318 return static_cast<double>(secs);
319 #endif /* !HAVE_FTIME */
323 // adds the elements of the env variable path to the arg passed in
324 void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
326 #if defined(_WIN32) && !defined(__CYGWIN__)
327 const char* pathSep = ";";
328 #else
329 const char* pathSep = ":";
330 #endif
331 if(!env)
333 env = "PATH";
335 const char* cpathEnv = SystemTools::GetEnv(env);
336 if ( !cpathEnv )
338 return;
341 kwsys_stl::string pathEnv = cpathEnv;
343 // A hack to make the below algorithm work.
344 if(pathEnv[pathEnv.length()-1] != ':')
346 pathEnv += pathSep;
348 kwsys_stl::string::size_type start =0;
349 bool done = false;
350 while(!done)
352 kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
353 if(endpos != kwsys_stl::string::npos)
355 kwsys_stl::string convertedPath;
356 Realpath(pathEnv.substr(start, endpos-start).c_str(), convertedPath);
357 path.push_back(convertedPath);
358 start = endpos+1;
360 else
362 done = true;
365 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
366 i != path.end(); ++i)
368 SystemTools::ConvertToUnixSlashes(*i);
372 const char* SystemTools::GetEnv(const char* key)
374 return getenv(key);
377 bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
379 const char* v = getenv(key);
380 if(v)
382 result = v;
383 return true;
385 else
387 return false;
391 const char* SystemTools::GetExecutableExtension()
393 #if defined(_WIN32) || defined(__CYGWIN__)
394 return ".exe";
395 #else
396 return "";
397 #endif
401 bool SystemTools::MakeDirectory(const char* path)
403 if(!path)
405 return false;
407 if(SystemTools::FileExists(path))
409 return true;
411 kwsys_stl::string dir = path;
412 if(dir.size() == 0)
414 return false;
416 SystemTools::ConvertToUnixSlashes(dir);
418 kwsys_stl::string::size_type pos = dir.find(':');
419 if(pos == kwsys_stl::string::npos)
421 pos = 0;
423 kwsys_stl::string topdir;
424 while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
426 topdir = dir.substr(0, pos);
427 Mkdir(topdir.c_str());
428 pos++;
430 if(dir[dir.size()-1] == '/')
432 topdir = dir.substr(0, dir.size());
434 else
436 topdir = dir;
438 if(Mkdir(topdir.c_str()) != 0)
440 // There is a bug in the Borland Run time library which makes MKDIR
441 // return EACCES when it should return EEXISTS
442 // if it is some other error besides directory exists
443 // then return false
444 if( (errno != EEXIST)
445 #ifdef __BORLANDC__
446 && (errno != EACCES)
447 #endif
450 return false;
453 return true;
457 // replace replace with with as many times as it shows up in source.
458 // write the result into source.
459 void SystemTools::ReplaceString(kwsys_stl::string& source,
460 const char* replace,
461 const char* with)
463 const char *src = source.c_str();
464 char *searchPos = const_cast<char *>(strstr(src,replace));
466 // get out quick if string is not found
467 if (!searchPos)
469 return;
472 // perform replacements until done
473 size_t replaceSize = strlen(replace);
474 // do while hangs if replaceSize is 0
475 if(replaceSize == 0)
477 return;
479 char *orig = strdup(src);
480 char *currentPos = orig;
481 searchPos = searchPos - src + orig;
483 // initialize the result
484 source.erase(source.begin(),source.end());
487 *searchPos = '\0';
488 source += currentPos;
489 currentPos = searchPos + replaceSize;
490 // replace
491 source += with;
492 searchPos = strstr(currentPos,replace);
494 while (searchPos);
496 // copy any trailing text
497 source += currentPos;
498 free(orig);
501 #if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
502 # define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
503 # define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
504 #else
505 # define KWSYS_ST_KEY_WOW64_32KEY 0x0200
506 # define KWSYS_ST_KEY_WOW64_64KEY 0x0100
507 #endif
509 #if defined(_WIN32) && !defined(__CYGWIN__)
510 static DWORD SystemToolsMakeRegistryMode(DWORD mode,
511 SystemTools::KeyWOW64 view)
513 if(view == SystemTools::KeyWOW64_32)
515 return mode | KWSYS_ST_KEY_WOW64_32KEY;
517 else if(view == SystemTools::KeyWOW64_64)
519 return mode | KWSYS_ST_KEY_WOW64_64KEY;
521 return mode;
523 #endif
525 // Read a registry value.
526 // Example :
527 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
528 // => will return the data of the "default" value of the key
529 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
530 // => will return the data of the "Root" value of the key
532 #if defined(_WIN32) && !defined(__CYGWIN__)
533 bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
534 KeyWOW64 view)
536 bool valueset = false;
537 kwsys_stl::string primary = key;
538 kwsys_stl::string second;
539 kwsys_stl::string valuename;
541 size_t start = primary.find("\\");
542 if (start == kwsys_stl::string::npos)
544 return false;
547 size_t valuenamepos = primary.find(";");
548 if (valuenamepos != kwsys_stl::string::npos)
550 valuename = primary.substr(valuenamepos+1);
553 second = primary.substr(start+1, valuenamepos-start-1);
554 primary = primary.substr(0, start);
556 HKEY primaryKey = HKEY_CURRENT_USER;
557 if (primary == "HKEY_CURRENT_USER")
559 primaryKey = HKEY_CURRENT_USER;
561 if (primary == "HKEY_CURRENT_CONFIG")
563 primaryKey = HKEY_CURRENT_CONFIG;
565 if (primary == "HKEY_CLASSES_ROOT")
567 primaryKey = HKEY_CLASSES_ROOT;
569 if (primary == "HKEY_LOCAL_MACHINE")
571 primaryKey = HKEY_LOCAL_MACHINE;
573 if (primary == "HKEY_USERS")
575 primaryKey = HKEY_USERS;
578 HKEY hKey;
579 if(RegOpenKeyEx(primaryKey,
580 second.c_str(),
582 SystemToolsMakeRegistryMode(KEY_READ, view),
583 &hKey) != ERROR_SUCCESS)
585 return false;
587 else
589 DWORD dwType, dwSize;
590 dwSize = 1023;
591 char data[1024];
592 if(RegQueryValueEx(hKey,
593 (LPTSTR)valuename.c_str(),
594 NULL,
595 &dwType,
596 (BYTE *)data,
597 &dwSize) == ERROR_SUCCESS)
599 if (dwType == REG_SZ)
601 value = data;
602 valueset = true;
604 else if (dwType == REG_EXPAND_SZ)
606 char expanded[1024];
607 DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]);
608 if(ExpandEnvironmentStrings(data, expanded, dwExpandedSize))
610 value = expanded;
611 valueset = true;
616 RegCloseKey(hKey);
619 return valueset;
621 #else
622 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
623 KeyWOW64)
625 return false;
627 #endif
630 // Write a registry value.
631 // Example :
632 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
633 // => will set the data of the "default" value of the key
634 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
635 // => will set the data of the "Root" value of the key
637 #if defined(_WIN32) && !defined(__CYGWIN__)
638 bool SystemTools::WriteRegistryValue(const char *key, const char *value,
639 KeyWOW64 view)
641 kwsys_stl::string primary = key;
642 kwsys_stl::string second;
643 kwsys_stl::string valuename;
645 size_t start = primary.find("\\");
646 if (start == kwsys_stl::string::npos)
648 return false;
651 size_t valuenamepos = primary.find(";");
652 if (valuenamepos != kwsys_stl::string::npos)
654 valuename = primary.substr(valuenamepos+1);
657 second = primary.substr(start+1, valuenamepos-start-1);
658 primary = primary.substr(0, start);
660 HKEY primaryKey = HKEY_CURRENT_USER;
661 if (primary == "HKEY_CURRENT_USER")
663 primaryKey = HKEY_CURRENT_USER;
665 if (primary == "HKEY_CURRENT_CONFIG")
667 primaryKey = HKEY_CURRENT_CONFIG;
669 if (primary == "HKEY_CLASSES_ROOT")
671 primaryKey = HKEY_CLASSES_ROOT;
673 if (primary == "HKEY_LOCAL_MACHINE")
675 primaryKey = HKEY_LOCAL_MACHINE;
677 if (primary == "HKEY_USERS")
679 primaryKey = HKEY_USERS;
682 HKEY hKey;
683 DWORD dwDummy;
684 if(RegCreateKeyEx(primaryKey,
685 second.c_str(),
688 REG_OPTION_NON_VOLATILE,
689 SystemToolsMakeRegistryMode(KEY_WRITE, view),
690 NULL,
691 &hKey,
692 &dwDummy) != ERROR_SUCCESS)
694 return false;
697 if(RegSetValueEx(hKey,
698 (LPTSTR)valuename.c_str(),
700 REG_SZ,
701 (CONST BYTE *)value,
702 (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
704 return true;
706 return false;
708 #else
709 bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
711 return false;
713 #endif
715 // Delete a registry value.
716 // Example :
717 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
718 // => will delete the data of the "default" value of the key
719 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
720 // => will delete the data of the "Root" value of the key
722 #if defined(_WIN32) && !defined(__CYGWIN__)
723 bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
725 kwsys_stl::string primary = key;
726 kwsys_stl::string second;
727 kwsys_stl::string valuename;
729 size_t start = primary.find("\\");
730 if (start == kwsys_stl::string::npos)
732 return false;
735 size_t valuenamepos = primary.find(";");
736 if (valuenamepos != kwsys_stl::string::npos)
738 valuename = primary.substr(valuenamepos+1);
741 second = primary.substr(start+1, valuenamepos-start-1);
742 primary = primary.substr(0, start);
744 HKEY primaryKey = HKEY_CURRENT_USER;
745 if (primary == "HKEY_CURRENT_USER")
747 primaryKey = HKEY_CURRENT_USER;
749 if (primary == "HKEY_CURRENT_CONFIG")
751 primaryKey = HKEY_CURRENT_CONFIG;
753 if (primary == "HKEY_CLASSES_ROOT")
755 primaryKey = HKEY_CLASSES_ROOT;
757 if (primary == "HKEY_LOCAL_MACHINE")
759 primaryKey = HKEY_LOCAL_MACHINE;
761 if (primary == "HKEY_USERS")
763 primaryKey = HKEY_USERS;
766 HKEY hKey;
767 if(RegOpenKeyEx(primaryKey,
768 second.c_str(),
770 SystemToolsMakeRegistryMode(KEY_WRITE, view),
771 &hKey) != ERROR_SUCCESS)
773 return false;
775 else
777 if(RegDeleteValue(hKey,
778 (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
780 RegCloseKey(hKey);
781 return true;
784 return false;
786 #else
787 bool SystemTools::DeleteRegistryValue(const char *, KeyWOW64)
789 return false;
791 #endif
793 bool SystemTools::SameFile(const char* file1, const char* file2)
795 #ifdef _WIN32
796 HANDLE hFile1, hFile2;
798 hFile1 = CreateFile( file1,
799 GENERIC_READ,
800 FILE_SHARE_READ ,
801 NULL,
802 OPEN_EXISTING,
803 FILE_FLAG_BACKUP_SEMANTICS,
804 NULL
806 hFile2 = CreateFile( file2,
807 GENERIC_READ,
808 FILE_SHARE_READ,
809 NULL,
810 OPEN_EXISTING,
811 FILE_FLAG_BACKUP_SEMANTICS,
812 NULL
814 if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
816 if(hFile1 != INVALID_HANDLE_VALUE)
818 CloseHandle(hFile1);
820 if(hFile2 != INVALID_HANDLE_VALUE)
822 CloseHandle(hFile2);
824 return false;
827 BY_HANDLE_FILE_INFORMATION fiBuf1;
828 BY_HANDLE_FILE_INFORMATION fiBuf2;
829 GetFileInformationByHandle( hFile1, &fiBuf1 );
830 GetFileInformationByHandle( hFile2, &fiBuf2 );
831 CloseHandle(hFile1);
832 CloseHandle(hFile2);
833 return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
834 fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
835 fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
836 #else
837 struct stat fileStat1, fileStat2;
838 if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
840 // see if the files are the same file
841 // check the device inode and size
842 if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
843 memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
844 fileStat2.st_size == fileStat1.st_size
847 return true;
850 return false;
851 #endif
855 // return true if the file exists
856 bool SystemTools::FileExists(const char* filename, bool isFile)
858 #ifdef _MSC_VER
859 # define access _access
860 #endif
861 #ifndef R_OK
862 # define R_OK 04
863 #endif
865 #ifdef __SYLLABLE__
866 if ((filename !=0) && (*filename == 0))
868 return false;
870 #endif
872 if ( access(filename, R_OK) != 0 )
874 return false;
876 else
878 // If isFile is set return not FileIsDirectory,
879 // so this will only be true if it is a file
880 if(isFile)
882 return !SystemTools::FileIsDirectory(filename);
884 return true;
888 bool SystemTools::Touch(const char* filename, bool create)
890 if(create && !SystemTools::FileExists(filename))
892 FILE* file = fopen(filename, "a+b");
893 if(file)
895 fclose(file);
896 return true;
898 return false;
900 #ifdef _MSC_VER
901 #define utime _utime
902 #define utimbuf _utimbuf
903 #endif
904 struct stat fromStat;
905 if(stat(filename, &fromStat) < 0)
907 return false;
909 struct utimbuf buf;
910 buf.actime = fromStat.st_atime;
911 buf.modtime = static_cast<time_t>(SystemTools::GetTime());
912 if(utime(filename, &buf) < 0)
914 return false;
916 return true;
919 bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
920 int* result)
922 // Default to same time.
923 *result = 0;
924 #if !defined(_WIN32) || defined(__CYGWIN__)
925 // POSIX version. Use stat function to get file modification time.
926 struct stat s1;
927 if(stat(f1, &s1) != 0)
929 return false;
931 struct stat s2;
932 if(stat(f2, &s2) != 0)
934 return false;
936 # if KWSYS_STAT_HAS_ST_MTIM
937 // Compare using nanosecond resolution.
938 if(s1.st_mtim.tv_sec < s2.st_mtim.tv_sec)
940 *result = -1;
942 else if(s1.st_mtim.tv_sec > s2.st_mtim.tv_sec)
944 *result = 1;
946 else if(s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec)
948 *result = -1;
950 else if(s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec)
952 *result = 1;
954 # else
955 // Compare using 1 second resolution.
956 if(s1.st_mtime < s2.st_mtime)
958 *result = -1;
960 else if(s1.st_mtime > s2.st_mtime)
962 *result = 1;
964 # endif
965 #else
966 // Windows version. Get the modification time from extended file attributes.
967 WIN32_FILE_ATTRIBUTE_DATA f1d;
968 WIN32_FILE_ATTRIBUTE_DATA f2d;
969 if(!GetFileAttributesEx(f1, GetFileExInfoStandard, &f1d))
971 return false;
973 if(!GetFileAttributesEx(f2, GetFileExInfoStandard, &f2d))
975 return false;
978 // Compare the file times using resolution provided by system call.
979 *result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime);
980 #endif
981 return true;
985 // Return a capitalized string (i.e the first letter is uppercased, all other
986 // are lowercased)
987 kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s)
989 kwsys_stl::string n;
990 if(s.size() == 0)
992 return n;
994 n.resize(s.size());
995 n[0] = static_cast<kwsys_stl::string::value_type>(toupper(s[0]));
996 for (size_t i = 1; i < s.size(); i++)
998 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1000 return n;
1003 // Return capitalized words
1004 kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s)
1006 kwsys_stl::string n(s);
1007 for (size_t i = 0; i < s.size(); i++)
1009 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1010 // MS has an assert that will fail if s[i] < 0; setting
1011 // LC_CTYPE using setlocale() does *not* help. Painful.
1012 if ((int)s[i] >= 0 && isalpha(s[i]) &&
1013 (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1]))))
1014 #else
1015 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
1016 #endif
1018 n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
1021 return n;
1024 // Return uncapitalized words
1025 kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s)
1027 kwsys_stl::string n(s);
1028 for (size_t i = 0; i < s.size(); i++)
1030 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1031 // MS has an assert that will fail if s[i] < 0; setting
1032 // LC_CTYPE using setlocale() does *not* help. Painful.
1033 if ((int)s[i] >= 0 && isalpha(s[i]) &&
1034 (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1]))))
1035 #else
1036 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
1037 #endif
1039 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1042 return n;
1045 // only works for words with at least two letters
1046 kwsys_stl::string SystemTools::AddSpaceBetweenCapitalizedWords(
1047 const kwsys_stl::string& s)
1049 kwsys_stl::string n;
1050 if (s.size())
1052 n.reserve(s.size());
1053 n += s[0];
1054 for (size_t i = 1; i < s.size(); i++)
1056 if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1]))
1058 n += ' ';
1060 n += s[i];
1063 return n;
1066 char* SystemTools::AppendStrings(const char* str1, const char* str2)
1068 if (!str1)
1070 return SystemTools::DuplicateString(str2);
1072 if (!str2)
1074 return SystemTools::DuplicateString(str1);
1076 size_t len1 = strlen(str1);
1077 char *newstr = new char[len1 + strlen(str2) + 1];
1078 if (!newstr)
1080 return 0;
1082 strcpy(newstr, str1);
1083 strcat(newstr + len1, str2);
1084 return newstr;
1087 char* SystemTools::AppendStrings(
1088 const char* str1, const char* str2, const char* str3)
1090 if (!str1)
1092 return SystemTools::AppendStrings(str2, str3);
1094 if (!str2)
1096 return SystemTools::AppendStrings(str1, str3);
1098 if (!str3)
1100 return SystemTools::AppendStrings(str1, str2);
1103 size_t len1 = strlen(str1), len2 = strlen(str2);
1104 char *newstr = new char[len1 + len2 + strlen(str3) + 1];
1105 if (!newstr)
1107 return 0;
1109 strcpy(newstr, str1);
1110 strcat(newstr + len1, str2);
1111 strcat(newstr + len1 + len2, str3);
1112 return newstr;
1115 // Return a lower case string
1116 kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s)
1118 kwsys_stl::string n;
1119 n.resize(s.size());
1120 for (size_t i = 0; i < s.size(); i++)
1122 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1124 return n;
1127 // Return a lower case string
1128 kwsys_stl::string SystemTools::UpperCase(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>(toupper(s[i]));
1136 return n;
1139 // Count char in string
1140 size_t SystemTools::CountChar(const char* str, char c)
1142 size_t count = 0;
1144 if (str)
1146 while (*str)
1148 if (*str == c)
1150 ++count;
1152 ++str;
1155 return count;
1158 // Remove chars in string
1159 char* SystemTools::RemoveChars(const char* str, const char *toremove)
1161 if (!str)
1163 return NULL;
1165 char *clean_str = new char [strlen(str) + 1];
1166 char *ptr = clean_str;
1167 while (*str)
1169 const char *str2 = toremove;
1170 while (*str2 && *str != *str2)
1172 ++str2;
1174 if (!*str2)
1176 *ptr++ = *str;
1178 ++str;
1180 *ptr = '\0';
1181 return clean_str;
1184 // Remove chars in string
1185 char* SystemTools::RemoveCharsButUpperHex(const char* str)
1187 if (!str)
1189 return 0;
1191 char *clean_str = new char [strlen(str) + 1];
1192 char *ptr = clean_str;
1193 while (*str)
1195 if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'F'))
1197 *ptr++ = *str;
1199 ++str;
1201 *ptr = '\0';
1202 return clean_str;
1205 // Replace chars in string
1206 char* SystemTools::ReplaceChars(char* str, const char *toreplace, char replacement)
1208 if (str)
1210 char *ptr = str;
1211 while (*ptr)
1213 const char *ptr2 = toreplace;
1214 while (*ptr2)
1216 if (*ptr == *ptr2)
1218 *ptr = replacement;
1220 ++ptr2;
1222 ++ptr;
1225 return str;
1228 // Returns if string starts with another string
1229 bool SystemTools::StringStartsWith(const char* str1, const char* str2)
1231 if (!str1 || !str2)
1233 return false;
1235 size_t len1 = strlen(str1), len2 = strlen(str2);
1236 return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false;
1239 // Returns if string ends with another string
1240 bool SystemTools::StringEndsWith(const char* str1, const char* str2)
1242 if (!str1 || !str2)
1244 return false;
1246 size_t len1 = strlen(str1), len2 = strlen(str2);
1247 return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true : false;
1250 // Returns a pointer to the last occurence of str2 in str1
1251 const char* SystemTools::FindLastString(const char* str1, const char* str2)
1253 if (!str1 || !str2)
1255 return NULL;
1258 size_t len1 = strlen(str1), len2 = strlen(str2);
1259 if (len1 >= len2)
1261 const char *ptr = str1 + len1 - len2;
1264 if (!strncmp(ptr, str2, len2))
1266 return ptr;
1268 } while (ptr-- != str1);
1271 return NULL;
1274 // Duplicate string
1275 char* SystemTools::DuplicateString(const char* str)
1277 if (str)
1279 char *newstr = new char [strlen(str) + 1];
1280 return strcpy(newstr, str);
1282 return NULL;
1285 // Return a cropped string
1286 kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
1287 size_t max_len)
1289 if (!s.size() || max_len == 0 || max_len >= s.size())
1291 return s;
1294 kwsys_stl::string n;
1295 n.reserve(max_len);
1297 size_t middle = max_len / 2;
1299 n += s.substr(0, middle);
1300 n += s.substr(s.size() - (max_len - middle), kwsys_stl::string::npos);
1302 if (max_len > 2)
1304 n[middle] = '.';
1305 if (max_len > 3)
1307 n[middle - 1] = '.';
1308 if (max_len > 4)
1310 n[middle + 1] = '.';
1315 return n;
1318 //----------------------------------------------------------------------------
1319 kwsys_stl::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
1321 kwsys_stl::string path = p;
1322 kwsys_stl::vector<kwsys::String> paths;
1323 if(isPath && path[0] == '/')
1325 path.erase(path.begin());
1326 paths.push_back("/");
1328 kwsys_stl::string::size_type pos1 = 0;
1329 kwsys_stl::string::size_type pos2 = path.find(sep, pos1+1);
1330 while(pos2 != kwsys_stl::string::npos)
1332 paths.push_back(path.substr(pos1, pos2-pos1));
1333 pos1 = pos2+1;
1334 pos2 = path.find(sep, pos1+1);
1336 paths.push_back(path.substr(pos1, pos2-pos1));
1338 return paths;
1341 //----------------------------------------------------------------------------
1342 int SystemTools::EstimateFormatLength(const char *format, va_list ap)
1344 if (!format)
1346 return 0;
1349 // Quick-hack attempt at estimating the length of the string.
1350 // Should never under-estimate.
1352 // Start with the length of the format string itself.
1354 size_t length = strlen(format);
1356 // Increase the length for every argument in the format.
1358 const char* cur = format;
1359 while(*cur)
1361 if(*cur++ == '%')
1363 // Skip "%%" since it doesn't correspond to a va_arg.
1364 if(*cur != '%')
1366 while(!int(isalpha(*cur)))
1368 ++cur;
1370 switch (*cur)
1372 case 's':
1374 // Check the length of the string.
1375 char* s = va_arg(ap, char*);
1376 if(s)
1378 length += strlen(s);
1380 } break;
1381 case 'e':
1382 case 'f':
1383 case 'g':
1385 // Assume the argument contributes no more than 64 characters.
1386 length += 64;
1388 // Eat the argument.
1389 static_cast<void>(va_arg(ap, double));
1390 } break;
1391 default:
1393 // Assume the argument contributes no more than 64 characters.
1394 length += 64;
1396 // Eat the argument.
1397 static_cast<void>(va_arg(ap, int));
1398 } break;
1402 // Move past the characters just tested.
1403 ++cur;
1407 return static_cast<int>(length);
1410 kwsys_stl::string SystemTools::EscapeChars(
1411 const char *str,
1412 const char *chars_to_escape,
1413 char escape_char)
1415 kwsys_stl::string n;
1416 if (str)
1418 if (!chars_to_escape | !*chars_to_escape)
1420 n.append(str);
1422 else
1424 n.reserve(strlen(str));
1425 while (*str)
1427 const char *ptr = chars_to_escape;
1428 while (*ptr)
1430 if (*str == *ptr)
1432 n += escape_char;
1433 break;
1435 ++ptr;
1437 n += *str;
1438 ++str;
1442 return n;
1445 // convert windows slashes to unix slashes
1446 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
1448 const char* pathCString = path.c_str();
1449 bool hasDoubleSlash = false;
1451 const char* pos0 = pathCString;
1452 const char* pos1 = pathCString+1;
1453 for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos )
1455 // make sure we don't convert an escaped space to a unix slash
1456 if ( *pos0 == '\\' && *pos1 != ' ' )
1458 path[pos] = '/';
1461 // Also, reuse the loop to check for slash followed by another slash
1462 if (*pos1 == '/' && *(pos1+1) == '/' && !hasDoubleSlash)
1464 #ifdef _WIN32
1465 // However, on windows if the first characters are both slashes,
1466 // then keep them that way, so that network paths can be handled.
1467 if ( pos > 0)
1469 hasDoubleSlash = true;
1471 #else
1472 hasDoubleSlash = true;
1473 #endif
1476 pos0 ++;
1477 pos1 ++;
1480 if ( hasDoubleSlash )
1482 SystemTools::ReplaceString(path, "//", "/");
1485 // remove any trailing slash
1486 if(!path.empty())
1488 // if there is a tilda ~ then replace it with HOME
1489 pathCString = path.c_str();
1490 if(pathCString[0] == '~' && (pathCString[1] == '/' || pathCString[1] == '\0'))
1492 const char* homeEnv = SystemTools::GetEnv("HOME");
1493 if (homeEnv)
1495 path.replace(0,1,homeEnv);
1498 #ifdef HAVE_GETPWNAM
1499 else if(pathCString[0] == '~')
1501 kwsys_stl::string::size_type idx = path.find_first_of("/\0");
1502 kwsys_stl::string user = path.substr(1, idx-1);
1503 passwd* pw = getpwnam(user.c_str());
1504 if(pw)
1506 path.replace(0, idx, pw->pw_dir);
1509 #endif
1510 // remove trailing slash if the path is more than
1511 // a single /
1512 pathCString = path.c_str();
1513 if(path.size() > 1 && *(pathCString+(path.size()-1)) == '/')
1515 // if it is c:/ then do not remove the trailing slash
1516 if(!((path.size() == 3 && pathCString[1] == ':')))
1518 path = path.substr(0, path.size()-1);
1524 // change // to /, and escape any spaces in the path
1525 kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
1527 kwsys_stl::string ret = path;
1529 // remove // except at the beginning might be a cygwin drive
1530 kwsys_stl::string::size_type pos=0;
1531 while((pos = ret.find("//", pos)) != kwsys_stl::string::npos)
1533 ret.erase(pos, 1);
1535 // escape spaces and () in the path
1536 if(ret.find_first_of(" ") != kwsys_stl::string::npos)
1538 kwsys_stl::string result = "";
1539 char lastch = 1;
1540 for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
1542 // if it is already escaped then don't try to escape it again
1543 if((*ch == ' ') && lastch != '\\')
1545 result += '\\';
1547 result += *ch;
1548 lastch = *ch;
1550 ret = result;
1552 return ret;
1555 kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path)
1557 #if defined(_WIN32) && !defined(__CYGWIN__)
1558 return SystemTools::ConvertToWindowsOutputPath(path);
1559 #else
1560 return SystemTools::ConvertToUnixOutputPath(path);
1561 #endif
1564 // remove double slashes not at the start
1565 kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path)
1567 kwsys_stl::string ret;
1568 // make it big enough for all of path and double quotes
1569 ret.reserve(strlen(path)+3);
1570 // put path into the string
1571 ret.assign(path);
1572 ret = path;
1573 kwsys_stl::string::size_type pos = 0;
1574 // first convert all of the slashes
1575 while((pos = ret.find('/', pos)) != kwsys_stl::string::npos)
1577 ret[pos] = '\\';
1578 pos++;
1580 // check for really small paths
1581 if(ret.size() < 2)
1583 return ret;
1585 // now clean up a bit and remove double slashes
1586 // Only if it is not the first position in the path which is a network
1587 // path on windows
1588 pos = 1; // start at position 1
1589 if(ret[0] == '\"')
1591 pos = 2; // if the string is already quoted then start at 2
1592 if(ret.size() < 3)
1594 return ret;
1597 while((pos = ret.find("\\\\", pos)) != kwsys_stl::string::npos)
1599 ret.erase(pos, 1);
1601 // now double quote the path if it has spaces in it
1602 // and is not already double quoted
1603 if(ret.find(' ') != kwsys_stl::string::npos
1604 && ret[0] != '\"')
1606 ret.insert(static_cast<kwsys_stl::string::size_type>(0),
1607 static_cast<kwsys_stl::string::size_type>(1), '\"');
1608 ret.append(1, '\"');
1610 return ret;
1613 bool SystemTools::CopyFileIfDifferent(const char* source,
1614 const char* destination)
1616 // special check for a destination that is a directory
1617 // FilesDiffer does not handle file to directory compare
1618 if(SystemTools::FileIsDirectory(destination))
1620 kwsys_stl::string new_destination = destination;
1621 SystemTools::ConvertToUnixSlashes(new_destination);
1622 new_destination += '/';
1623 kwsys_stl::string source_name = source;
1624 new_destination += SystemTools::GetFilenameName(source_name);
1625 if(SystemTools::FilesDiffer(source, new_destination.c_str()))
1627 return SystemTools::CopyFileAlways(source, destination);
1629 else
1631 // the files are the same so the copy is done return
1632 // true
1633 return true;
1636 // source and destination are files so do a copy if they
1637 // are different
1638 if(SystemTools::FilesDiffer(source, destination))
1640 return SystemTools::CopyFileAlways(source, destination);
1642 // at this point the files must be the same so return true
1643 return true;
1646 #define KWSYS_ST_BUFFER 4096
1648 bool SystemTools::FilesDiffer(const char* source,
1649 const char* destination)
1651 struct stat statSource;
1652 if (stat(source, &statSource) != 0)
1654 return true;
1657 struct stat statDestination;
1658 if (stat(destination, &statDestination) != 0)
1660 return true;
1663 if(statSource.st_size != statDestination.st_size)
1665 return true;
1668 if(statSource.st_size == 0)
1670 return false;
1673 #if defined(_WIN32) || defined(__CYGWIN__)
1674 kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
1675 kwsys_ios::ios::in));
1676 kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
1677 kwsys_ios::ios::in));
1678 #else
1679 kwsys_ios::ifstream finSource(source);
1680 kwsys_ios::ifstream finDestination(destination);
1681 #endif
1682 if(!finSource || !finDestination)
1684 return true;
1687 // Compare the files a block at a time.
1688 char source_buf[KWSYS_ST_BUFFER];
1689 char dest_buf[KWSYS_ST_BUFFER];
1690 off_t nleft = statSource.st_size;
1691 while(nleft > 0)
1693 // Read a block from each file.
1694 kwsys_ios::streamsize nnext = (nleft > KWSYS_ST_BUFFER)? KWSYS_ST_BUFFER : static_cast<kwsys_ios::streamsize>(nleft);
1695 finSource.read(source_buf, nnext);
1696 finDestination.read(dest_buf, nnext);
1698 // If either failed to read assume they are different.
1699 if(static_cast<kwsys_ios::streamsize>(finSource.gcount()) != nnext ||
1700 static_cast<kwsys_ios::streamsize>(finDestination.gcount()) != nnext)
1702 return true;
1705 // If this block differs the file differs.
1706 if(memcmp(static_cast<const void*>(source_buf),
1707 static_cast<const void*>(dest_buf), nnext) != 0)
1709 return true;
1712 // Update the byte count remaining.
1713 nleft -= nnext;
1716 // No differences found.
1717 return false;
1722 * Copy a file named by "source" to the file named by "destination".
1724 bool SystemTools::CopyFileAlways(const char* source, const char* destination)
1726 // If files are the same do not copy
1727 if ( SystemTools::SameFile(source, destination) )
1729 return true;
1731 mode_t perm = 0;
1732 bool perms = SystemTools::GetPermissions(source, perm);
1734 const int bufferSize = 4096;
1735 char buffer[bufferSize];
1737 // If destination is a directory, try to create a file with the same
1738 // name as the source in that directory.
1740 kwsys_stl::string new_destination;
1741 if(SystemTools::FileExists(destination) &&
1742 SystemTools::FileIsDirectory(destination))
1744 new_destination = destination;
1745 SystemTools::ConvertToUnixSlashes(new_destination);
1746 new_destination += '/';
1747 kwsys_stl::string source_name = source;
1748 new_destination += SystemTools::GetFilenameName(source_name);
1749 destination = new_destination.c_str();
1752 // Create destination directory
1754 kwsys_stl::string destination_dir = destination;
1755 destination_dir = SystemTools::GetFilenamePath(destination_dir);
1756 SystemTools::MakeDirectory(destination_dir.c_str());
1758 // Open files
1760 #if defined(_WIN32) || defined(__CYGWIN__)
1761 kwsys_ios::ifstream fin(source,
1762 kwsys_ios::ios::binary | kwsys_ios::ios::in);
1763 #else
1764 kwsys_ios::ifstream fin(source);
1765 #endif
1766 if(!fin)
1768 return false;
1771 // try and remove the destination file so that read only destination files
1772 // can be written to.
1773 // If the remove fails continue so that files in read only directories
1774 // that do not allow file removal can be modified.
1775 SystemTools::RemoveFile(destination);
1777 #if defined(_WIN32) || defined(__CYGWIN__)
1778 kwsys_ios::ofstream fout(destination,
1779 kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1780 #else
1781 kwsys_ios::ofstream fout(destination,
1782 kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1783 #endif
1784 if(!fout)
1786 return false;
1789 // This copy loop is very sensitive on certain platforms with
1790 // slightly broken stream libraries (like HPUX). Normally, it is
1791 // incorrect to not check the error condition on the fin.read()
1792 // before using the data, but the fin.gcount() will be zero if an
1793 // error occurred. Therefore, the loop should be safe everywhere.
1794 while(fin)
1796 fin.read(buffer, bufferSize);
1797 if(fin.gcount())
1799 fout.write(buffer, fin.gcount());
1803 // Make sure the operating system has finished writing the file
1804 // before closing it. This will ensure the file is finished before
1805 // the check below.
1806 fout.flush();
1808 fin.close();
1809 fout.close();
1811 // More checks.
1812 struct stat statSource, statDestination;
1813 statSource.st_size = 12345;
1814 statDestination.st_size = 12345;
1815 if(stat(source, &statSource) != 0)
1817 return false;
1819 else if(stat(destination, &statDestination) != 0)
1821 return false;
1823 else if(statSource.st_size != statDestination.st_size)
1825 return false;
1827 if ( perms )
1829 if ( !SystemTools::SetPermissions(destination, perm) )
1831 return false;
1834 return true;
1837 //----------------------------------------------------------------------------
1838 bool SystemTools::CopyAFile(const char* source, const char* destination,
1839 bool always)
1841 if(always)
1843 return SystemTools::CopyFileAlways(source, destination);
1845 else
1847 return SystemTools::CopyFileIfDifferent(source, destination);
1852 * Copy a directory content from "source" directory to the directory named by
1853 * "destination".
1855 bool SystemTools::CopyADirectory(const char* source, const char* destination,
1856 bool always)
1858 Directory dir;
1859 dir.Load(source);
1860 size_t fileNum;
1861 if ( !SystemTools::MakeDirectory(destination) )
1863 return false;
1865 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
1867 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
1868 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
1870 kwsys_stl::string fullPath = source;
1871 fullPath += "/";
1872 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1873 if(SystemTools::FileIsDirectory(fullPath.c_str()))
1875 kwsys_stl::string fullDestPath = destination;
1876 fullDestPath += "/";
1877 fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1878 if (!SystemTools::CopyADirectory(fullPath.c_str(),
1879 fullDestPath.c_str(),
1880 always))
1882 return false;
1885 else
1887 if(!SystemTools::CopyAFile(fullPath.c_str(), destination, always))
1889 return false;
1895 return true;
1899 // return size of file; also returns zero if no file exists
1900 unsigned long SystemTools::FileLength(const char* filename)
1902 struct stat fs;
1903 if (stat(filename, &fs) != 0)
1905 return 0;
1907 else
1909 return static_cast<unsigned long>(fs.st_size);
1913 int SystemTools::Strucmp(const char *s1, const char *s2)
1915 // lifted from Graphvis http://www.graphviz.org
1916 while ((*s1 != '\0')
1917 && (tolower(*s1) == tolower(*s2)))
1919 s1++;
1920 s2++;
1923 return tolower(*s1) - tolower(*s2);
1926 // return file's modified time
1927 long int SystemTools::ModifiedTime(const char* filename)
1929 struct stat fs;
1930 if (stat(filename, &fs) != 0)
1932 return 0;
1934 else
1936 return static_cast<long int>(fs.st_mtime);
1940 // return file's creation time
1941 long int SystemTools::CreationTime(const char* filename)
1943 struct stat fs;
1944 if (stat(filename, &fs) != 0)
1946 return 0;
1948 else
1950 return fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0;
1954 bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt)
1956 if (!str || !tmt || strlen(str) > 11)
1958 return false;
1961 struct tm tmt2;
1963 // __DATE__
1964 // The compilation date of the current source file. The date is a string
1965 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
1966 // dates generated by the library function asctime declared in TIME.H.
1968 // index: 012345678901
1969 // format: Mmm dd yyyy
1970 // example: Dec 19 2003
1972 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1974 char buffer[12];
1975 strcpy(buffer, str);
1977 buffer[3] = 0;
1978 char *ptr = strstr(month_names, buffer);
1979 if (!ptr)
1981 return false;
1984 int month = (ptr - month_names) / 3;
1985 int day = atoi(buffer + 4);
1986 int year = atoi(buffer + 7);
1988 tmt2.tm_isdst = -1;
1989 tmt2.tm_hour = 0;
1990 tmt2.tm_min = 0;
1991 tmt2.tm_sec = 0;
1992 tmt2.tm_wday = 0;
1993 tmt2.tm_yday = 0;
1994 tmt2.tm_mday = day;
1995 tmt2.tm_mon = month;
1996 tmt2.tm_year = year - 1900;
1998 *tmt = mktime(&tmt2);
1999 return true;
2002 bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt)
2004 if (!str || !tmt || strlen(str) > 26)
2006 return false;
2009 struct tm tmt2;
2011 // __TIMESTAMP__
2012 // The date and time of the last modification of the current source file,
2013 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
2014 /// where Ddd is the abbreviated day of the week and Date is an integer
2015 // from 1 to 31.
2017 // index: 0123456789
2018 // 0123456789
2019 // 0123456789
2020 // format: Ddd Mmm Date hh:mm:ss yyyy
2021 // example: Fri Dec 19 14:34:58 2003
2023 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
2025 char buffer[27];
2026 strcpy(buffer, str);
2028 buffer[7] = 0;
2029 char *ptr = strstr(month_names, buffer + 4);
2030 if (!ptr)
2032 return false;
2035 int month = (ptr - month_names) / 3;
2036 int day = atoi(buffer + 8);
2037 int hour = atoi(buffer + 11);
2038 int min = atoi(buffer + 14);
2039 int sec = atoi(buffer + 17);
2040 int year = atoi(buffer + 20);
2042 tmt2.tm_isdst = -1;
2043 tmt2.tm_hour = hour;
2044 tmt2.tm_min = min;
2045 tmt2.tm_sec = sec;
2046 tmt2.tm_wday = 0;
2047 tmt2.tm_yday = 0;
2048 tmt2.tm_mday = day;
2049 tmt2.tm_mon = month;
2050 tmt2.tm_year = year - 1900;
2052 *tmt = mktime(&tmt2);
2053 return true;
2056 kwsys_stl::string SystemTools::GetLastSystemError()
2058 int e = errno;
2059 return strerror(e);
2062 bool SystemTools::RemoveFile(const char* source)
2064 #ifdef _WIN32
2065 mode_t mode;
2066 if ( !SystemTools::GetPermissions(source, mode) )
2068 return false;
2070 /* Win32 unlink is stupid --- it fails if the file is read-only */
2071 SystemTools::SetPermissions(source, S_IWRITE);
2072 #endif
2073 bool res = unlink(source) != 0 ? false : true;
2074 #ifdef _WIN32
2075 if ( !res )
2077 SystemTools::SetPermissions(source, mode);
2079 #endif
2080 return res;
2083 bool SystemTools::RemoveADirectory(const char* source)
2085 Directory dir;
2086 dir.Load(source);
2087 size_t fileNum;
2088 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
2090 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
2091 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
2093 kwsys_stl::string fullPath = source;
2094 fullPath += "/";
2095 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
2096 if(SystemTools::FileIsDirectory(fullPath.c_str()) &&
2097 !SystemTools::FileIsSymlink(fullPath.c_str()))
2099 if (!SystemTools::RemoveADirectory(fullPath.c_str()))
2101 return false;
2104 else
2106 if(!SystemTools::RemoveFile(fullPath.c_str()))
2108 return false;
2114 return (Rmdir(source) == 0);
2119 size_t SystemTools::GetMaximumFilePathLength()
2121 return KWSYS_SYSTEMTOOLS_MAXPATH;
2125 * Find the file the given name. Searches the given path and then
2126 * the system search path. Returns the full path to the file if it is
2127 * found. Otherwise, the empty string is returned.
2129 kwsys_stl::string SystemTools
2130 ::FindName(const char* name,
2131 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2132 bool no_system_path)
2134 // Add the system search path to our path first
2135 kwsys_stl::vector<kwsys_stl::string> path;
2136 if (!no_system_path)
2138 SystemTools::GetPath(path, "CMAKE_FILE_PATH");
2139 SystemTools::GetPath(path);
2141 // now add the additional paths
2143 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
2144 i != userPaths.end(); ++i)
2146 path.push_back(*i);
2149 // Add a trailing slash to all paths to aid the search process.
2151 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2152 i != path.end(); ++i)
2154 kwsys_stl::string& p = *i;
2155 if(p.empty() || p[p.size()-1] != '/')
2157 p += "/";
2161 // now look for the file
2162 kwsys_stl::string tryPath;
2163 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
2164 p != path.end(); ++p)
2166 tryPath = *p;
2167 tryPath += name;
2168 if(SystemTools::FileExists(tryPath.c_str()))
2170 return tryPath;
2173 // Couldn't find the file.
2174 return "";
2178 * Find the file the given name. Searches the given path and then
2179 * the system search path. Returns the full path to the file if it is
2180 * found. Otherwise, the empty string is returned.
2182 kwsys_stl::string SystemTools
2183 ::FindFile(const char* name,
2184 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2185 bool no_system_path)
2187 kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
2188 if(tryPath != "" && !SystemTools::FileIsDirectory(tryPath.c_str()))
2190 return SystemTools::CollapseFullPath(tryPath.c_str());
2192 // Couldn't find the file.
2193 return "";
2197 * Find the directory the given name. Searches the given path and then
2198 * the system search path. Returns the full path to the directory if it is
2199 * found. Otherwise, the empty string is returned.
2201 kwsys_stl::string SystemTools
2202 ::FindDirectory(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 executable with the given name. Searches the given path and then
2217 * the system search path. Returns the full path to the executable if it is
2218 * found. Otherwise, the empty string is returned.
2220 kwsys_stl::string SystemTools::FindProgram(
2221 const char* nameIn,
2222 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2223 bool no_system_path)
2225 if(!nameIn || !*nameIn)
2227 return "";
2229 kwsys_stl::string name = nameIn;
2230 kwsys_stl::vector<kwsys_stl::string> extensions;
2231 #if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
2232 bool hasExtension = false;
2233 // check to see if the name already has a .xxx at
2234 // the end of it
2235 if(name.size() > 3 && name[name.size()-4] == '.')
2237 hasExtension = true;
2239 // on windows try .com then .exe
2240 if(!hasExtension)
2242 extensions.push_back(".com");
2243 extensions.push_back(".exe");
2245 #endif
2246 kwsys_stl::string tryPath;
2248 // first try with extensions if the os supports them
2249 if(extensions.size())
2251 for(kwsys_stl::vector<kwsys_stl::string>::iterator i =
2252 extensions.begin(); i != extensions.end(); ++i)
2254 tryPath = name;
2255 tryPath += *i;
2256 if(SystemTools::FileExists(tryPath.c_str()) &&
2257 !SystemTools::FileIsDirectory(tryPath.c_str()))
2259 return SystemTools::CollapseFullPath(tryPath.c_str());
2263 // now try just the name
2264 tryPath = name;
2265 if(SystemTools::FileExists(tryPath.c_str()) &&
2266 !SystemTools::FileIsDirectory(tryPath.c_str()))
2268 return SystemTools::CollapseFullPath(tryPath.c_str());
2270 // now construct the path
2271 kwsys_stl::vector<kwsys_stl::string> path;
2272 // Add the system search path to our path.
2273 if (!no_system_path)
2275 SystemTools::GetPath(path);
2277 // now add the additional paths
2279 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i =
2280 userPaths.begin(); i != userPaths.end(); ++i)
2282 path.push_back(*i);
2285 // Add a trailing slash to all paths to aid the search process.
2287 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2288 i != path.end(); ++i)
2290 kwsys_stl::string& p = *i;
2291 if(p.empty() || p[p.size()-1] != '/')
2293 p += "/";
2297 // Try each path
2298 for(kwsys_stl::vector<kwsys_stl::string>::iterator p = path.begin();
2299 p != path.end(); ++p)
2301 #ifdef _WIN32
2302 // Remove double quotes from the path on windows
2303 SystemTools::ReplaceString(*p, "\"", "");
2304 #endif
2305 // first try with extensions
2306 if(extensions.size())
2308 for(kwsys_stl::vector<kwsys_stl::string>::iterator ext
2309 = extensions.begin(); ext != extensions.end(); ++ext)
2311 tryPath = *p;
2312 tryPath += name;
2313 tryPath += *ext;
2314 if(SystemTools::FileExists(tryPath.c_str()) &&
2315 !SystemTools::FileIsDirectory(tryPath.c_str()))
2317 return SystemTools::CollapseFullPath(tryPath.c_str());
2321 // now try it without them
2322 tryPath = *p;
2323 tryPath += name;
2324 if(SystemTools::FileExists(tryPath.c_str()) &&
2325 !SystemTools::FileIsDirectory(tryPath.c_str()))
2327 return SystemTools::CollapseFullPath(tryPath.c_str());
2330 // Couldn't find the program.
2331 return "";
2334 kwsys_stl::string SystemTools::FindProgram(
2335 const kwsys_stl::vector<kwsys_stl::string>& names,
2336 const kwsys_stl::vector<kwsys_stl::string>& path,
2337 bool noSystemPath)
2339 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator it = names.begin();
2340 it != names.end() ; ++it)
2342 // Try to find the program.
2343 kwsys_stl::string result = SystemTools::FindProgram(it->c_str(),
2344 path,
2345 noSystemPath);
2346 if ( !result.empty() )
2348 return result;
2351 return "";
2355 * Find the library with the given name. Searches the given path and then
2356 * the system search path. Returns the full path to the library if it is
2357 * found. Otherwise, the empty string is returned.
2359 kwsys_stl::string SystemTools
2360 ::FindLibrary(const char* name,
2361 const kwsys_stl::vector<kwsys_stl::string>& userPaths)
2363 // See if the executable exists as written.
2364 if(SystemTools::FileExists(name) &&
2365 !SystemTools::FileIsDirectory(name))
2367 return SystemTools::CollapseFullPath(name);
2370 // Add the system search path to our path.
2371 kwsys_stl::vector<kwsys_stl::string> path;
2372 SystemTools::GetPath(path);
2373 // now add the additional paths
2375 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
2376 i != userPaths.end(); ++i)
2378 path.push_back(*i);
2381 // Add a trailing slash to all paths to aid the search process.
2383 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2384 i != path.end(); ++i)
2386 kwsys_stl::string& p = *i;
2387 if(p.empty() || p[p.size()-1] != '/')
2389 p += "/";
2393 kwsys_stl::string tryPath;
2394 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
2395 p != path.end(); ++p)
2397 #if defined(__APPLE__)
2398 tryPath = *p;
2399 tryPath += name;
2400 tryPath += ".framework";
2401 if(SystemTools::FileExists(tryPath.c_str())
2402 && SystemTools::FileIsDirectory(tryPath.c_str()))
2404 return SystemTools::CollapseFullPath(tryPath.c_str());
2406 #endif
2407 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
2408 tryPath = *p;
2409 tryPath += name;
2410 tryPath += ".lib";
2411 if(SystemTools::FileExists(tryPath.c_str())
2412 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2414 return SystemTools::CollapseFullPath(tryPath.c_str());
2416 #else
2417 tryPath = *p;
2418 tryPath += "lib";
2419 tryPath += name;
2420 tryPath += ".so";
2421 if(SystemTools::FileExists(tryPath.c_str())
2422 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2424 return SystemTools::CollapseFullPath(tryPath.c_str());
2426 tryPath = *p;
2427 tryPath += "lib";
2428 tryPath += name;
2429 tryPath += ".a";
2430 if(SystemTools::FileExists(tryPath.c_str())
2431 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2433 return SystemTools::CollapseFullPath(tryPath.c_str());
2435 tryPath = *p;
2436 tryPath += "lib";
2437 tryPath += name;
2438 tryPath += ".sl";
2439 if(SystemTools::FileExists(tryPath.c_str())
2440 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2442 return SystemTools::CollapseFullPath(tryPath.c_str());
2444 tryPath = *p;
2445 tryPath += "lib";
2446 tryPath += name;
2447 tryPath += ".dylib";
2448 if(SystemTools::FileExists(tryPath.c_str())
2449 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2451 return SystemTools::CollapseFullPath(tryPath.c_str());
2453 tryPath = *p;
2454 tryPath += "lib";
2455 tryPath += name;
2456 tryPath += ".dll";
2457 if(SystemTools::FileExists(tryPath.c_str())
2458 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2460 return SystemTools::CollapseFullPath(tryPath.c_str());
2462 #endif
2465 // Couldn't find the library.
2466 return "";
2469 kwsys_stl::string SystemTools::GetRealPath(const char* path)
2471 kwsys_stl::string ret;
2472 Realpath(path, ret);
2473 return ret;
2476 bool SystemTools::FileIsDirectory(const char* name)
2478 // Remove any trailing slash from the name.
2479 char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
2480 int last = static_cast<int>(strlen(name))-1;
2481 if(last > 0 && (name[last] == '/' || name[last] == '\\')
2482 && strcmp(name, "/") !=0)
2484 memcpy(buffer, name, last);
2485 buffer[last] = 0;
2486 name = buffer;
2489 // Now check the file node type.
2490 struct stat fs;
2491 if(stat(name, &fs) == 0)
2493 #if defined( _WIN32 )
2494 return ((fs.st_mode & _S_IFDIR) != 0);
2495 #else
2496 return S_ISDIR(fs.st_mode);
2497 #endif
2499 else
2501 return false;
2505 bool SystemTools::FileIsSymlink(const char* name)
2507 #if defined( _WIN32 )
2508 (void)name;
2509 return false;
2510 #else
2511 struct stat fs;
2512 if(lstat(name, &fs) == 0)
2514 return S_ISLNK(fs.st_mode);
2516 else
2518 return false;
2520 #endif
2523 #if defined(_WIN32) && !defined(__CYGWIN__)
2524 bool SystemTools::CreateSymlink(const char*, const char*)
2526 return false;
2528 #else
2529 bool SystemTools::CreateSymlink(const char* origName, const char* newName)
2531 return symlink(origName, newName) >= 0;
2533 #endif
2535 #if defined(_WIN32) && !defined(__CYGWIN__)
2536 bool SystemTools::ReadSymlink(const char*, kwsys_stl::string&)
2538 return false;
2540 #else
2541 bool SystemTools::ReadSymlink(const char* newName,
2542 kwsys_stl::string& origName)
2544 char buf[KWSYS_SYSTEMTOOLS_MAXPATH+1];
2545 int count =
2546 static_cast<int>(readlink(newName, buf, KWSYS_SYSTEMTOOLS_MAXPATH));
2547 if(count >= 0)
2549 // Add null-terminator.
2550 buf[count] = 0;
2551 origName = buf;
2552 return true;
2554 else
2556 return false;
2559 #endif
2561 int SystemTools::ChangeDirectory(const char *dir)
2563 return Chdir(dir);
2566 kwsys_stl::string SystemTools::GetCurrentWorkingDirectory(bool collapse)
2568 char buf[2048];
2569 const char* cwd = Getcwd(buf, 2048);
2570 kwsys_stl::string path;
2571 if ( cwd )
2573 path = cwd;
2575 if(collapse)
2577 return SystemTools::CollapseFullPath(path.c_str());
2579 return path;
2582 kwsys_stl::string SystemTools::GetProgramPath(const char* in_name)
2584 kwsys_stl::string dir, file;
2585 SystemTools::SplitProgramPath(in_name, dir, file);
2586 return dir;
2589 bool SystemTools::SplitProgramPath(const char* in_name,
2590 kwsys_stl::string& dir,
2591 kwsys_stl::string& file,
2592 bool)
2594 dir = in_name;
2595 file = "";
2596 SystemTools::ConvertToUnixSlashes(dir);
2598 if(!SystemTools::FileIsDirectory(dir.c_str()))
2600 kwsys_stl::string::size_type slashPos = dir.rfind("/");
2601 if(slashPos != kwsys_stl::string::npos)
2603 file = dir.substr(slashPos+1);
2604 dir = dir.substr(0, slashPos);
2606 else
2608 file = dir;
2609 dir = "";
2612 if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str()))
2614 kwsys_stl::string oldDir = in_name;
2615 SystemTools::ConvertToUnixSlashes(oldDir);
2616 dir = in_name;
2617 return false;
2619 return true;
2622 bool SystemTools::FindProgramPath(const char* argv0,
2623 kwsys_stl::string& pathOut,
2624 kwsys_stl::string& errorMsg,
2625 const char* exeName,
2626 const char* buildDir,
2627 const char* installPrefix )
2629 kwsys_stl::vector<kwsys_stl::string> failures;
2630 kwsys_stl::string self = argv0 ? argv0 : "";
2631 failures.push_back(self);
2632 SystemTools::ConvertToUnixSlashes(self);
2633 self = SystemTools::FindProgram(self.c_str());
2634 if(!SystemTools::FileExists(self.c_str()))
2636 if(buildDir)
2638 kwsys_stl::string intdir = ".";
2639 #ifdef CMAKE_INTDIR
2640 intdir = CMAKE_INTDIR;
2641 #endif
2642 self = buildDir;
2643 self += "/bin/";
2644 self += intdir;
2645 self += "/";
2646 self += exeName;
2647 self += SystemTools::GetExecutableExtension();
2650 if(installPrefix)
2652 if(!SystemTools::FileExists(self.c_str()))
2654 failures.push_back(self);
2655 self = installPrefix;
2656 self += "/bin/";
2657 self += exeName;
2660 if(!SystemTools::FileExists(self.c_str()))
2662 failures.push_back(self);
2663 kwsys_ios::ostringstream msg;
2664 msg << "Can not find the command line program ";
2665 if (exeName)
2667 msg << exeName;
2669 msg << "\n";
2670 if (argv0)
2672 msg << " argv[0] = \"" << argv0 << "\"\n";
2674 msg << " Attempted paths:\n";
2675 kwsys_stl::vector<kwsys_stl::string>::iterator i;
2676 for(i=failures.begin(); i != failures.end(); ++i)
2678 msg << " \"" << i->c_str() << "\"\n";
2680 errorMsg = msg.str();
2681 return false;
2683 pathOut = self;
2684 return true;
2688 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative)
2690 return SystemTools::CollapseFullPath(in_relative, 0);
2693 void SystemTools::AddTranslationPath(const char * a, const char * b)
2695 kwsys_stl::string path_a = a;
2696 kwsys_stl::string path_b = b;
2697 SystemTools::ConvertToUnixSlashes(path_a);
2698 SystemTools::ConvertToUnixSlashes(path_b);
2699 // First check this is a directory path, since we don't want the table to
2700 // grow too fat
2701 if( SystemTools::FileIsDirectory( path_a.c_str() ) )
2703 // Make sure the path is a full path and does not contain no '..'
2704 // Ken--the following code is incorrect. .. can be in a valid path
2705 // for example /home/martink/MyHubba...Hubba/Src
2706 if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..")
2707 == kwsys_stl::string::npos )
2709 // Before inserting make sure path ends with '/'
2710 if(path_a.size() && path_a[path_a.size() -1] != '/')
2712 path_a += '/';
2714 if(path_b.size() && path_b[path_b.size() -1] != '/')
2716 path_b += '/';
2718 if( !(path_a == path_b) )
2720 SystemTools::TranslationMap->insert(
2721 SystemToolsTranslationMap::value_type(path_a, path_b));
2727 void SystemTools::AddKeepPath(const char* dir)
2729 kwsys_stl::string cdir;
2730 Realpath(SystemTools::CollapseFullPath(dir).c_str(), cdir);
2731 SystemTools::AddTranslationPath(cdir.c_str(), dir);
2734 void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
2736 // Do not translate paths that are too short to have meaningful
2737 // translations.
2738 if(path.size() < 2)
2740 return;
2743 // Always add a trailing slash before translation. It does not
2744 // matter if this adds an extra slash, but we do not want to
2745 // translate part of a directory (like the foo part of foo-dir).
2746 path += "/";
2748 // In case a file was specified we still have to go through this:
2749 // Now convert any path found in the table back to the one desired:
2750 kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>::const_iterator it;
2751 for(it = SystemTools::TranslationMap->begin();
2752 it != SystemTools::TranslationMap->end();
2753 ++it )
2755 // We need to check of the path is a substring of the other path
2756 if(path.find( it->first ) == 0)
2758 path = path.replace( 0, it->first.size(), it->second);
2762 // Remove the trailing slash we added before.
2763 path.erase(path.end()-1, path.end());
2766 void
2767 SystemToolsAppendComponents(
2768 kwsys_stl::vector<kwsys_stl::string>& out_components,
2769 kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
2770 kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
2772 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = first;
2773 i != last; ++i)
2775 if(*i == "..")
2777 if(out_components.begin() != out_components.end())
2779 out_components.erase(out_components.end()-1, out_components.end());
2782 else if(!(*i == ".") && !(*i == ""))
2784 out_components.push_back(*i);
2789 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
2790 const char* in_base)
2792 // Collect the output path components.
2793 kwsys_stl::vector<kwsys_stl::string> out_components;
2795 // Split the input path components.
2796 kwsys_stl::vector<kwsys_stl::string> path_components;
2797 SystemTools::SplitPath(in_path, path_components);
2799 // If the input path is relative, start with a base path.
2800 if(path_components[0].length() == 0)
2802 kwsys_stl::vector<kwsys_stl::string> base_components;
2803 if(in_base)
2805 // Use the given base path.
2806 SystemTools::SplitPath(in_base, base_components);
2808 else
2810 // Use the current working directory as a base path.
2811 char buf[2048];
2812 if(const char* cwd = Getcwd(buf, 2048))
2814 SystemTools::SplitPath(cwd, base_components);
2816 else
2818 // ??
2822 // Append base path components to the output path.
2823 out_components.push_back(base_components[0]);
2824 SystemToolsAppendComponents(out_components,
2825 base_components.begin()+1,
2826 base_components.end());
2829 // Append input path components to the output path.
2830 SystemToolsAppendComponents(out_components,
2831 path_components.begin(),
2832 path_components.end());
2834 // Transform the path back to a string.
2835 kwsys_stl::string newPath = SystemTools::JoinPath(out_components);
2837 // Update the translation table with this potentially new path. I am not
2838 // sure why this line is here, it seems really questionable, but yet I
2839 // would put good money that if I remove it something will break, basically
2840 // from what I can see it created a mapping from the collapsed path, to be
2841 // replaced by the input path, which almost completely does the opposite of
2842 // this function, the only thing preventing this from happening a lot is
2843 // that if the in_path has a .. in it, then it is not added to the
2844 // translation table. So for most calls this either does nothing due to the
2845 // .. or it adds a translation between identical paths as nothing was
2846 // collapsed, so I am going to try to comment it out, and see what hits the
2847 // fan, hopefully quickly.
2848 // Commented out line below:
2849 //SystemTools::AddTranslationPath(newPath.c_str(), in_path);
2851 SystemTools::CheckTranslationPath(newPath);
2852 #ifdef _WIN32
2853 newPath = SystemTools::GetActualCaseForPath(newPath.c_str());
2854 SystemTools::ConvertToUnixSlashes(newPath);
2855 #endif
2856 // Return the reconstructed path.
2857 return newPath;
2860 // compute the relative path from here to there
2861 kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remote)
2863 if(!SystemTools::FileIsFullPath(local))
2865 return "";
2867 if(!SystemTools::FileIsFullPath(remote))
2869 return "";
2872 // split up both paths into arrays of strings using / as a separator
2873 kwsys_stl::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true);
2874 kwsys_stl::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true);
2875 kwsys_stl::vector<kwsys::String> commonPath; // store shared parts of path in this array
2876 kwsys_stl::vector<kwsys::String> finalPath; // store the final relative path here
2877 // count up how many matching directory names there are from the start
2878 unsigned int sameCount = 0;
2879 while(
2880 ((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1)))
2882 // for windows and apple do a case insensitive string compare
2883 #if defined(_WIN32) || defined(__APPLE__)
2884 SystemTools::Strucmp(localSplit[sameCount].c_str(),
2885 remoteSplit[sameCount].c_str()) == 0
2886 #else
2887 localSplit[sameCount] == remoteSplit[sameCount]
2888 #endif
2891 // put the common parts of the path into the commonPath array
2892 commonPath.push_back(localSplit[sameCount]);
2893 // erase the common parts of the path from the original path arrays
2894 localSplit[sameCount] = "";
2895 remoteSplit[sameCount] = "";
2896 sameCount++;
2899 // If there is nothing in common at all then just return the full
2900 // path. This is the case only on windows when the paths have
2901 // different drive letters. On unix two full paths always at least
2902 // have the root "/" in common so we will return a relative path
2903 // that passes through the root directory.
2904 if(sameCount == 0)
2906 return remote;
2909 // for each entry that is not common in the local path
2910 // add a ../ to the finalpath array, this gets us out of the local
2911 // path into the remote dir
2912 for(unsigned int i = 0; i < localSplit.size(); ++i)
2914 if(localSplit[i].size())
2916 finalPath.push_back("../");
2919 // for each entry that is not common in the remote path add it
2920 // to the final path.
2921 for(kwsys_stl::vector<String>::iterator vit = remoteSplit.begin();
2922 vit != remoteSplit.end(); ++vit)
2924 if(vit->size())
2926 finalPath.push_back(*vit);
2929 kwsys_stl::string relativePath; // result string
2930 // now turn the array of directories into a unix path by puttint /
2931 // between each entry that does not already have one
2932 for(kwsys_stl::vector<String>::iterator vit1 = finalPath.begin();
2933 vit1 != finalPath.end(); ++vit1)
2935 if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
2937 relativePath += "/";
2939 relativePath += *vit1;
2941 return relativePath;
2944 // OK, some fun stuff to get the actual case of a given path.
2945 // Basically, you just need to call ShortPath, then GetLongPathName,
2946 // However, GetLongPathName is not implemented on windows NT and 95,
2947 // so we have to simulate it on those versions
2948 #ifdef _WIN32
2949 int OldWindowsGetLongPath(kwsys_stl::string const& shortPath,
2950 kwsys_stl::string& longPath )
2952 kwsys_stl::string::size_type iFound = shortPath.rfind('/');
2953 if (iFound > 1 && iFound != shortPath.npos)
2955 // recurse to peel off components
2957 if (OldWindowsGetLongPath(shortPath.substr(0, iFound), longPath) > 0)
2959 longPath += '/';
2960 if (shortPath[1] != '/')
2962 WIN32_FIND_DATA findData;
2964 // append the long component name to the path
2966 if (INVALID_HANDLE_VALUE != ::FindFirstFile
2967 (shortPath.c_str(), &findData))
2969 longPath += findData.cFileName;
2971 else
2973 // if FindFirstFile fails, return the error code
2975 longPath = "";
2976 return 0;
2981 else
2983 longPath = shortPath;
2985 return (int)longPath.size();
2989 int PortableGetLongPathName(const char* pathIn,
2990 kwsys_stl::string & longPath)
2992 HMODULE lh = LoadLibrary("Kernel32.dll");
2993 if(lh)
2995 FARPROC proc = GetProcAddress(lh, "GetLongPathNameA");
2996 if(proc)
2998 typedef DWORD (WINAPI * GetLongFunctionPtr) (LPCSTR,LPSTR,DWORD);
2999 GetLongFunctionPtr func = (GetLongFunctionPtr)proc;
3000 char buffer[MAX_PATH+1];
3001 int len = (*func)(pathIn, buffer, MAX_PATH+1);
3002 if(len == 0 || len > MAX_PATH+1)
3004 FreeLibrary(lh);
3005 return 0;
3007 longPath = buffer;
3008 FreeLibrary(lh);
3009 return len;
3011 FreeLibrary(lh);
3013 return OldWindowsGetLongPath(pathIn, longPath);
3015 #endif
3018 //----------------------------------------------------------------------------
3019 kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p)
3021 #ifndef _WIN32
3022 return p;
3023 #else
3024 // Check to see if actual case has already been called
3025 // for this path, and the result is stored in the LongPathMap
3026 SystemToolsTranslationMap::iterator i =
3027 SystemTools::LongPathMap->find(p);
3028 if(i != SystemTools::LongPathMap->end())
3030 return i->second;
3032 kwsys_stl::string shortPath;
3033 if(!SystemTools::GetShortPath(p, shortPath))
3035 return p;
3037 kwsys_stl::string longPath;
3038 int len = PortableGetLongPathName(shortPath.c_str(), longPath);
3039 if(len == 0 || len > MAX_PATH+1)
3041 return p;
3043 // make sure drive letter is always upper case
3044 if(longPath.size() > 1 && longPath[1] == ':')
3046 longPath[0] = toupper(longPath[0]);
3048 (*SystemTools::LongPathMap)[p] = longPath;
3049 return longPath;
3050 #endif
3053 //----------------------------------------------------------------------------
3054 const char* SystemTools::SplitPathRootComponent(const char* p,
3055 kwsys_stl::string* root)
3057 // Identify the root component.
3058 const char* c = p;
3059 if((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\'))
3061 // Network path.
3062 if(root)
3064 *root = "//";
3066 c += 2;
3068 else if(c[0] == '/')
3070 // Unix path.
3071 if(root)
3073 *root = "/";
3075 c += 1;
3077 else if(c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\'))
3079 // Windows path.
3080 if(root)
3082 (*root) = "_:/";
3083 (*root)[0] = c[0];
3085 c += 3;
3087 else if(c[0] && c[1] == ':')
3089 // Path relative to a windows drive working directory.
3090 if(root)
3092 (*root) = "_:";
3093 (*root)[0] = c[0];
3095 c += 2;
3097 else if(c[0] == '~')
3099 // Home directory. The returned root should always have a
3100 // trailing slash so that appending components as
3101 // c[0]c[1]/c[2]/... works. The remaining path returned should
3102 // skip the first slash if it exists:
3104 // "~" : root = "~/" , return ""
3105 // "~/ : root = "~/" , return ""
3106 // "~/x : root = "~/" , return "x"
3107 // "~u" : root = "~u/", return ""
3108 // "~u/" : root = "~u/", return ""
3109 // "~u/x" : root = "~u/", return "x"
3110 int n = 1;
3111 while(c[n] && c[n] != '/')
3113 ++n;
3115 if(root)
3117 root->assign(c, n);
3118 *root += '/';
3120 if(c[n] == '/')
3122 ++n;
3124 c += n;
3126 else
3128 // Relative path.
3129 if(root)
3131 *root = "";
3135 // Return the remaining path.
3136 return c;
3139 //----------------------------------------------------------------------------
3140 void SystemTools::SplitPath(const char* p,
3141 kwsys_stl::vector<kwsys_stl::string>& components,
3142 bool expand_home_dir)
3144 const char* c = p;
3145 components.clear();
3147 // Identify the root component.
3149 kwsys_stl::string root;
3150 c = SystemTools::SplitPathRootComponent(c, &root);
3152 // Expand home directory references if requested.
3153 if(expand_home_dir && !root.empty() && root[0] == '~')
3155 kwsys_stl::string homedir;
3156 root = root.substr(0, root.size()-1);
3157 if(root.size() == 1)
3159 #if defined(_WIN32) && !defined(__CYGWIN__)
3160 if(const char* userp = getenv("USERPROFILE"))
3162 homedir = userp;
3164 else
3165 #endif
3166 if(const char* h = getenv("HOME"))
3168 homedir = h;
3171 #ifdef HAVE_GETPWNAM
3172 else if(passwd* pw = getpwnam(root.c_str()+1))
3174 if(pw->pw_dir)
3176 homedir = pw->pw_dir;
3179 #endif
3180 if(!homedir.empty() && (homedir[homedir.size()-1] == '/' ||
3181 homedir[homedir.size()-1] == '\\'))
3183 homedir = homedir.substr(0, homedir.size()-1);
3185 SystemTools::SplitPath(homedir.c_str(), components);
3187 else
3189 components.push_back(root);
3193 // Parse the remaining components.
3194 const char* first = c;
3195 const char* last = first;
3196 for(;*last; ++last)
3198 if(*last == '/' || *last == '\\')
3200 // End of a component. Save it.
3201 components.push_back(kwsys_stl::string(first, last-first));
3202 first = last+1;
3206 // Save the last component unless there were no components.
3207 if(last != c)
3209 components.push_back(kwsys_stl::string(first, last-first));
3213 //----------------------------------------------------------------------------
3214 kwsys_stl::string
3215 SystemTools::JoinPath(const kwsys_stl::vector<kwsys_stl::string>& components)
3217 return SystemTools::JoinPath(components.begin(), components.end());
3220 //----------------------------------------------------------------------------
3221 kwsys_stl::string
3222 SystemTools
3223 ::JoinPath(kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
3224 kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
3226 // Construct result in a single string.
3227 kwsys_stl::string result;
3229 // The first two components do not add a slash.
3230 if(first != last)
3232 result += *first++;
3234 if(first != last)
3236 result += *first++;
3239 // All remaining components are always separated with a slash.
3240 while(first != last)
3242 result += "/";
3243 result += *first++;
3246 // Return the concatenated result.
3247 return result;
3250 //----------------------------------------------------------------------------
3251 bool SystemTools::ComparePath(const char* c1, const char* c2)
3253 #if defined(_WIN32) || defined(__APPLE__)
3254 # ifdef _MSC_VER
3255 return _stricmp(c1, c2) == 0;
3256 # elif defined(__APPLE__) || defined(__GNUC__)
3257 return strcasecmp(c1, c2) == 0;
3258 #else
3259 return SystemTools::Strucmp(c1, c2) == 0;
3260 # endif
3261 #else
3262 return strcmp(c1, c2) == 0;
3263 #endif
3266 //----------------------------------------------------------------------------
3267 bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines, char separator)
3269 kwsys_stl::string data(str);
3270 kwsys_stl::string::size_type lpos = 0;
3271 while(lpos < data.length())
3273 kwsys_stl::string::size_type rpos = data.find_first_of(separator, lpos);
3274 if(rpos == kwsys_stl::string::npos)
3276 // Line ends at end of string without a newline.
3277 lines.push_back(data.substr(lpos));
3278 return false;
3280 else
3282 // Line ends in a "\n", remove the character.
3283 lines.push_back(data.substr(lpos, rpos-lpos));
3285 lpos = rpos+1;
3287 return true;
3290 //----------------------------------------------------------------------------
3291 bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines)
3293 kwsys_stl::string data(str);
3294 kwsys_stl::string::size_type lpos = 0;
3295 while(lpos < data.length())
3297 kwsys_stl::string::size_type rpos = data.find_first_of("\n", lpos);
3298 if(rpos == kwsys_stl::string::npos)
3300 // Line ends at end of string without a newline.
3301 lines.push_back(data.substr(lpos));
3302 return false;
3304 if((rpos > lpos) && (data[rpos-1] == '\r'))
3306 // Line ends in a "\r\n" pair, remove both characters.
3307 lines.push_back(data.substr(lpos, (rpos-1)-lpos));
3309 else
3311 // Line ends in a "\n", remove the character.
3312 lines.push_back(data.substr(lpos, rpos-lpos));
3314 lpos = rpos+1;
3316 return true;
3320 * Return path of a full filename (no trailing slashes).
3321 * Warning: returned path is converted to Unix slashes format.
3323 kwsys_stl::string SystemTools::GetFilenamePath(const kwsys_stl::string& filename)
3325 kwsys_stl::string fn = filename;
3326 SystemTools::ConvertToUnixSlashes(fn);
3328 kwsys_stl::string::size_type slash_pos = fn.rfind("/");
3329 if(slash_pos != kwsys_stl::string::npos)
3331 kwsys_stl::string ret = fn.substr(0, slash_pos);
3332 if(ret.size() == 2 && ret[1] == ':')
3334 return ret + '/';
3336 if(ret.size() == 0)
3338 return "/";
3340 return ret;
3342 else
3344 return "";
3350 * Return file name of a full filename (i.e. file name without path).
3352 kwsys_stl::string SystemTools::GetFilenameName(const kwsys_stl::string& filename)
3354 #if defined(_WIN32)
3355 kwsys_stl::string::size_type slash_pos = filename.find_last_of("/\\");
3356 #else
3357 kwsys_stl::string::size_type slash_pos = filename.find_last_of("/");
3358 #endif
3359 if(slash_pos != kwsys_stl::string::npos)
3361 return filename.substr(slash_pos + 1);
3363 else
3365 return filename;
3371 * Return file extension of a full filename (dot included).
3372 * Warning: this is the longest extension (for example: .tar.gz)
3374 kwsys_stl::string SystemTools::GetFilenameExtension(const kwsys_stl::string& filename)
3376 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3377 kwsys_stl::string::size_type dot_pos = name.find(".");
3378 if(dot_pos != kwsys_stl::string::npos)
3380 return name.substr(dot_pos);
3382 else
3384 return "";
3389 * Return file extension of a full filename (dot included).
3390 * Warning: this is the shortest extension (for example: .gz of .tar.gz)
3392 kwsys_stl::string SystemTools::GetFilenameLastExtension(const kwsys_stl::string& filename)
3394 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3395 kwsys_stl::string::size_type dot_pos = name.rfind(".");
3396 if(dot_pos != kwsys_stl::string::npos)
3398 return name.substr(dot_pos);
3400 else
3402 return "";
3407 * Return file name without extension of a full filename (i.e. without path).
3408 * Warning: it considers the longest extension (for example: .tar.gz)
3410 kwsys_stl::string SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string& filename)
3412 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3413 kwsys_stl::string::size_type dot_pos = name.find(".");
3414 if(dot_pos != kwsys_stl::string::npos)
3416 return name.substr(0, dot_pos);
3418 else
3420 return name;
3426 * Return file name without extension of a full filename (i.e. without path).
3427 * Warning: it considers the last extension (for example: removes .gz
3428 * from .tar.gz)
3430 kwsys_stl::string
3431 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string& filename)
3433 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3434 kwsys_stl::string::size_type dot_pos = name.rfind(".");
3435 if(dot_pos != kwsys_stl::string::npos)
3437 return name.substr(0, dot_pos);
3439 else
3441 return name;
3445 bool SystemTools::FileHasSignature(const char *filename,
3446 const char *signature,
3447 long offset)
3449 if (!filename || !signature)
3451 return false;
3454 FILE *fp;
3455 fp = fopen(filename, "rb");
3456 if (!fp)
3458 return false;
3461 fseek(fp, offset, SEEK_SET);
3463 bool res = false;
3464 size_t signature_len = strlen(signature);
3465 char *buffer = new char [signature_len];
3467 if (fread(buffer, 1, signature_len, fp) == signature_len)
3469 res = (!strncmp(buffer, signature, signature_len) ? true : false);
3472 delete [] buffer;
3474 fclose(fp);
3475 return res;
3478 SystemTools::FileTypeEnum
3479 SystemTools::DetectFileType(const char *filename,
3480 unsigned long length,
3481 double percent_bin)
3483 if (!filename || percent_bin < 0)
3485 return SystemTools::FileTypeUnknown;
3488 FILE *fp;
3489 fp = fopen(filename, "rb");
3490 if (!fp)
3492 return SystemTools::FileTypeUnknown;
3495 // Allocate buffer and read bytes
3497 unsigned char *buffer = new unsigned char [length];
3498 size_t read_length = fread(buffer, 1, length, fp);
3499 fclose(fp);
3500 if (read_length == 0)
3502 return SystemTools::FileTypeUnknown;
3505 // Loop over contents and count
3507 size_t text_count = 0;
3509 const unsigned char *ptr = buffer;
3510 const unsigned char *buffer_end = buffer + read_length;
3512 while (ptr != buffer_end)
3514 if ((*ptr >= 0x20 && *ptr <= 0x7F) ||
3515 *ptr == '\n' ||
3516 *ptr == '\r' ||
3517 *ptr == '\t')
3519 text_count++;
3521 ptr++;
3524 delete [] buffer;
3526 double current_percent_bin =
3527 (static_cast<double>(read_length - text_count) /
3528 static_cast<double>(read_length));
3530 if (current_percent_bin >= percent_bin)
3532 return SystemTools::FileTypeBinary;
3535 return SystemTools::FileTypeText;
3538 bool SystemTools::LocateFileInDir(const char *filename,
3539 const char *dir,
3540 kwsys_stl::string& filename_found,
3541 int try_filename_dirs)
3543 if (!filename || !dir)
3545 return false;
3548 // Get the basename of 'filename'
3550 kwsys_stl::string filename_base = SystemTools::GetFilenameName(filename);
3552 // Check if 'dir' is really a directory
3553 // If win32 and matches something like C:, accept it as a dir
3555 kwsys_stl::string real_dir;
3556 if (!SystemTools::FileIsDirectory(dir))
3558 #if defined( _WIN32 )
3559 size_t dir_len = strlen(dir);
3560 if (dir_len < 2 || dir[dir_len - 1] != ':')
3562 #endif
3563 real_dir = SystemTools::GetFilenamePath(dir);
3564 dir = real_dir.c_str();
3565 #if defined( _WIN32 )
3567 #endif
3570 // Try to find the file in 'dir'
3572 bool res = false;
3573 if (filename_base.size() && dir)
3575 size_t dir_len = strlen(dir);
3576 int need_slash =
3577 (dir_len && dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\');
3579 kwsys_stl::string temp = dir;
3580 if (need_slash)
3582 temp += "/";
3584 temp += filename_base;
3586 if (SystemTools::FileExists(temp.c_str()))
3588 res = true;
3589 filename_found = temp;
3592 // If not found, we can try harder by appending part of the file to
3593 // to the directory to look inside.
3594 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
3595 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
3597 else if (try_filename_dirs)
3599 kwsys_stl::string filename_dir(filename);
3600 kwsys_stl::string filename_dir_base;
3601 kwsys_stl::string filename_dir_bases;
3604 filename_dir = SystemTools::GetFilenamePath(filename_dir);
3605 filename_dir_base = SystemTools::GetFilenameName(filename_dir);
3606 #if defined( _WIN32 )
3607 if (!filename_dir_base.size() ||
3608 filename_dir_base[filename_dir_base.size() - 1] == ':')
3609 #else
3610 if (!filename_dir_base.size())
3611 #endif
3613 break;
3616 filename_dir_bases = filename_dir_base + "/" + filename_dir_bases;
3618 temp = dir;
3619 if (need_slash)
3621 temp += "/";
3623 temp += filename_dir_bases;
3625 res = SystemTools::LocateFileInDir(
3626 filename_base.c_str(), temp.c_str(), filename_found, 0);
3628 } while (!res && filename_dir_base.size());
3632 return res;
3635 bool SystemTools::FileIsFullPath(const char* in_name)
3637 kwsys_stl::string name = in_name;
3638 #if defined(_WIN32) || defined(__CYGWIN__)
3639 // On Windows, the name must be at least two characters long.
3640 if(name.length() < 2)
3642 return false;
3644 if(name[1] == ':')
3646 return true;
3648 if(name[0] == '\\')
3650 return true;
3652 #else
3653 // On UNIX, the name must be at least one character long.
3654 if(name.length() < 1)
3656 return false;
3658 #endif
3659 #if !defined(_WIN32)
3660 if(name[0] == '~')
3662 return true;
3664 #endif
3665 // On UNIX, the name must begin in a '/'.
3666 // On Windows, if the name begins in a '/', then it is a full
3667 // network path.
3668 if(name[0] == '/')
3670 return true;
3672 return false;
3675 bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
3677 #if defined(WIN32) && !defined(__CYGWIN__)
3678 const int size = int(strlen(path)) +1; // size of return
3679 char *buffer = new char[size]; // create a buffer
3680 char *tempPath = new char[size]; // create a buffer
3681 int ret;
3683 // if the path passed in has quotes around it, first remove the quotes
3684 if (path[0] == '"' && path[strlen(path)-1] == '"')
3686 strcpy(tempPath,path+1);
3687 tempPath[strlen(tempPath)-1] = '\0';
3689 else
3691 strcpy(tempPath,path);
3694 buffer[0] = 0;
3695 ret = GetShortPathName(tempPath, buffer, size);
3697 if(buffer[0] == 0 || ret > size)
3699 delete [] buffer;
3700 delete [] tempPath;
3701 return false;
3703 else
3705 shortPath = buffer;
3706 delete [] buffer;
3707 delete [] tempPath;
3708 return true;
3710 #else
3711 shortPath = path;
3712 return true;
3713 #endif
3716 void SystemTools::SplitProgramFromArgs(const char* path,
3717 kwsys_stl::string& program, kwsys_stl::string& args)
3719 // see if this is a full path to a program
3720 // if so then set program to path and args to nothing
3721 if(SystemTools::FileExists(path))
3723 program = path;
3724 args = "";
3725 return;
3727 // Try to find the program in the path, note the program
3728 // may have spaces in its name so we have to look for it
3729 kwsys_stl::vector<kwsys_stl::string> e;
3730 kwsys_stl::string findProg = SystemTools::FindProgram(path, e);
3731 if(findProg.size())
3733 program = findProg;
3734 args = "";
3735 return;
3738 // Now try and peel off space separated chunks from the end of the string
3739 // so the largest path possible is found allowing for spaces in the path
3740 kwsys_stl::string dir = path;
3741 kwsys_stl::string::size_type spacePos = dir.rfind(' ');
3742 while(spacePos != kwsys_stl::string::npos)
3744 kwsys_stl::string tryProg = dir.substr(0, spacePos);
3745 // See if the file exists
3746 if(SystemTools::FileExists(tryProg.c_str()))
3748 program = tryProg;
3749 // remove trailing spaces from program
3750 kwsys_stl::string::size_type pos = program.size()-1;
3751 while(program[pos] == ' ')
3753 program.erase(pos);
3754 pos--;
3756 args = dir.substr(spacePos, dir.size()-spacePos);
3757 return;
3759 // Now try and find the the program in the path
3760 findProg = SystemTools::FindProgram(tryProg.c_str(), e);
3761 if(findProg.size())
3763 program = findProg;
3764 // remove trailing spaces from program
3765 kwsys_stl::string::size_type pos = program.size()-1;
3766 while(program[pos] == ' ')
3768 program.erase(pos);
3769 pos--;
3771 args = dir.substr(spacePos, dir.size()-spacePos);
3772 return;
3774 // move past the space for the next search
3775 spacePos--;
3776 spacePos = dir.rfind(' ', spacePos);
3779 program = "";
3780 args = "";
3783 kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format)
3785 char buf[1024];
3786 time_t t;
3787 time(&t);
3788 strftime(buf, sizeof(buf), format, localtime(&t));
3789 return kwsys_stl::string(buf);
3792 kwsys_stl::string SystemTools::MakeCindentifier(const char* s)
3794 kwsys_stl::string str(s);
3795 if (str.find_first_of("0123456789") == 0)
3797 str = "_" + str;
3800 kwsys_stl::string permited_chars("_"
3801 "abcdefghijklmnopqrstuvwxyz"
3802 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3803 "0123456789");
3804 kwsys_stl::string::size_type pos = 0;
3805 while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_stl::string::npos)
3807 str[pos] = '_';
3809 return str;
3812 // Due to a buggy stream library on the HP and another on Mac OS X, we
3813 // need this very carefully written version of getline. Returns true
3814 // if any data were read before the end-of-file was reached.
3815 bool SystemTools::GetLineFromStream(kwsys_ios::istream& is,
3816 kwsys_stl::string& line,
3817 bool* has_newline /* = 0 */,
3818 long sizeLimit /* = -1 */)
3820 const int bufferSize = 1024;
3821 char buffer[bufferSize];
3822 bool haveData = false;
3823 bool haveNewline = false;
3825 // Start with an empty line.
3826 line = "";
3828 long leftToRead = sizeLimit;
3830 // If no characters are read from the stream, the end of file has
3831 // been reached. Clear the fail bit just before reading.
3832 while(!haveNewline &&
3833 leftToRead != 0 &&
3834 (is.clear(is.rdstate() & ~kwsys_ios::ios::failbit),
3835 is.getline(buffer, bufferSize), is.gcount() > 0))
3837 // We have read at least one byte.
3838 haveData = true;
3840 // If newline character was read the gcount includes the character
3841 // but the buffer does not: the end of line has been reached.
3842 size_t length = strlen(buffer);
3843 if(length < static_cast<size_t>(is.gcount()))
3845 haveNewline = true;
3848 // Avoid storing a carriage return character.
3849 if(length > 0 && buffer[length-1] == '\r')
3851 buffer[length-1] = 0;
3854 // if we read too much then truncate the buffer
3855 if (leftToRead > 0)
3857 if (static_cast<long>(length) > leftToRead)
3859 buffer[leftToRead-1] = 0;
3860 leftToRead = 0;
3862 else
3864 leftToRead -= static_cast<long>(length);
3868 // Append the data read to the line.
3869 line.append(buffer);
3870 sizeLimit = sizeLimit - static_cast<long>(length);
3873 // Return the results.
3874 if(has_newline)
3876 *has_newline = haveNewline;
3878 return haveData;
3881 int SystemTools::GetTerminalWidth()
3883 int width = -1;
3884 #ifdef HAVE_TTY_INFO
3885 struct winsize ws;
3886 char *columns; /* Unix98 environment variable */
3887 if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0)
3889 width = ws.ws_col;
3891 if(!isatty(STDOUT_FILENO))
3893 width = -1;
3895 columns = getenv("COLUMNS");
3896 if(columns && *columns)
3898 long t;
3899 char *endptr;
3900 t = strtol(columns, &endptr, 0);
3901 if(endptr && !*endptr && (t>0) && (t<1000))
3903 width = static_cast<int>(t);
3906 if ( width < 9 )
3908 width = -1;
3910 #endif
3911 return width;
3914 bool SystemTools::GetPermissions(const char* file, mode_t& mode)
3916 if ( !file )
3918 return false;
3921 struct stat st;
3922 if ( stat(file, &st) < 0 )
3924 return false;
3926 mode = st.st_mode;
3927 return true;
3930 bool SystemTools::SetPermissions(const char* file, mode_t mode)
3932 if ( !file )
3934 return false;
3936 if ( !SystemTools::FileExists(file) )
3938 return false;
3940 if ( chmod(file, mode) < 0 )
3942 return false;
3945 return true;
3948 kwsys_stl::string SystemTools::GetParentDirectory(const char* fileOrDir)
3950 if ( !fileOrDir || !*fileOrDir )
3952 return "";
3954 kwsys_stl::string res = fileOrDir;
3955 SystemTools::ConvertToUnixSlashes(res);
3956 kwsys_stl::string::size_type cc = res.size()-1;
3957 if ( res[cc] == '/' )
3959 cc --;
3961 for ( ; cc > 0; cc -- )
3963 if ( res[cc] == '/' )
3965 break;
3968 return res.substr(0, cc);
3971 bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir)
3973 kwsys_stl::string subdir = cSubdir;
3974 kwsys_stl::string dir = cDir;
3975 SystemTools::ConvertToUnixSlashes(dir);
3976 kwsys_stl::string path = subdir;
3979 path = SystemTools::GetParentDirectory(path.c_str());
3980 if(SystemTools::ComparePath(dir.c_str(), path.c_str()))
3982 return true;
3985 while ( path.size() > dir.size() );
3986 return false;
3989 kwsys_stl::string SystemTools::FileExistsInParentDirectories(const char* fname,
3990 const char* directory, const char* toplevel)
3992 kwsys_stl::string file = fname;
3993 SystemTools::ConvertToUnixSlashes(file);
3994 kwsys_stl::string dir = directory;
3995 SystemTools::ConvertToUnixSlashes(dir);
3996 while ( !dir.empty() )
3998 kwsys_stl::string path = dir + "/" + file;
3999 if ( SystemTools::FileExists(path.c_str()) )
4001 return path;
4003 if ( dir.size() < strlen(toplevel) )
4005 break;
4007 dir = SystemTools::GetParentDirectory(dir.c_str());
4009 return "";
4012 void SystemTools::Delay(unsigned int msec)
4014 #ifdef _WIN32
4015 Sleep(msec);
4016 #else
4017 // The sleep function gives 1 second resolution and the usleep
4018 // function gives 1e-6 second resolution but on some platforms has a
4019 // maximum sleep time of 1 second. This could be re-implemented to
4020 // use select with masked signals or pselect to mask signals
4021 // atomically. If select is given empty sets and zero as the max
4022 // file descriptor but a non-zero timeout it can be used to block
4023 // for a precise amount of time.
4024 if(msec >= 1000)
4026 sleep(msec / 1000);
4027 usleep((msec % 1000) * 1000);
4029 else
4031 usleep(msec * 1000);
4033 #endif
4036 void SystemTools::ConvertWindowsCommandLineToUnixArguments(
4037 const char *cmd_line, int *argc, char ***argv)
4039 if (!cmd_line || !argc || !argv)
4041 return;
4044 // A space delimites an argument except when it is inside a quote
4046 (*argc) = 1;
4048 size_t cmd_line_len = strlen(cmd_line);
4050 size_t i;
4051 for (i = 0; i < cmd_line_len; i++)
4053 while (isspace(cmd_line[i]) && i < cmd_line_len)
4055 i++;
4057 if (i < cmd_line_len)
4059 if (cmd_line[i] == '\"')
4061 i++;
4062 while (cmd_line[i] != '\"' && i < cmd_line_len)
4064 i++;
4066 (*argc)++;
4068 else
4070 while (!isspace(cmd_line[i]) && i < cmd_line_len)
4072 i++;
4074 (*argc)++;
4079 (*argv) = new char* [(*argc) + 1];
4080 (*argv)[(*argc)] = NULL;
4082 // Set the first arg to be the exec name
4084 (*argv)[0] = new char [1024];
4085 #ifdef _WIN32
4086 ::GetModuleFileName(0, (*argv)[0], 1024);
4087 #else
4088 (*argv)[0][0] = '\0';
4089 #endif
4091 // Allocate the others
4093 int j;
4094 for (j = 1; j < (*argc); j++)
4096 (*argv)[j] = new char [cmd_line_len + 10];
4099 // Grab the args
4101 size_t pos;
4102 int argc_idx = 1;
4104 for (i = 0; i < cmd_line_len; i++)
4106 while (isspace(cmd_line[i]) && i < cmd_line_len)
4108 i++;
4110 if (i < cmd_line_len)
4112 if (cmd_line[i] == '\"')
4114 i++;
4115 pos = i;
4116 while (cmd_line[i] != '\"' && i < cmd_line_len)
4118 i++;
4120 memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
4121 (*argv)[argc_idx][i - pos] = '\0';
4122 argc_idx++;
4124 else
4126 pos = i;
4127 while (!isspace(cmd_line[i]) && i < cmd_line_len)
4129 i++;
4131 memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
4132 (*argv)[argc_idx][i - pos] = '\0';
4133 argc_idx++;
4139 kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
4141 kwsys_stl::string res;
4143 #ifdef _WIN32
4144 char buffer[256];
4146 OSVERSIONINFOEX osvi;
4147 BOOL bOsVersionInfoEx;
4149 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
4150 // If that fails, try using the OSVERSIONINFO structure.
4152 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
4153 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
4155 bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
4156 if (!bOsVersionInfoEx)
4158 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
4159 if (!GetVersionEx((OSVERSIONINFO *)&osvi))
4161 return 0;
4165 switch (osvi.dwPlatformId)
4167 // Test for the Windows NT product family.
4169 case VER_PLATFORM_WIN32_NT:
4171 // Test for the specific product family.
4173 if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
4175 #if (_MSC_VER >= 1300)
4176 if (osvi.wProductType == VER_NT_WORKSTATION)
4178 res += "Microsoft Windows Vista";
4180 else
4182 res += "Microsoft Windows Server 2008 family";
4184 #else
4185 res += "Microsoft Windows Vista or Windows Server 2008";
4186 #endif
4189 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
4191 res += "Microsoft Windows Server 2003 family";
4194 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
4196 res += "Microsoft Windows XP";
4199 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
4201 res += "Microsoft Windows 2000";
4204 if (osvi.dwMajorVersion <= 4)
4206 res += "Microsoft Windows NT";
4209 // Test for specific product on Windows NT 4.0 SP6 and later.
4211 if (bOsVersionInfoEx)
4213 // Test for the workstation type.
4215 #if (_MSC_VER >= 1300)
4216 if (osvi.wProductType == VER_NT_WORKSTATION)
4218 if (osvi.dwMajorVersion == 4)
4220 res += " Workstation 4.0";
4222 else if (osvi.dwMajorVersion == 5)
4224 if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
4226 res += " Home Edition";
4228 else
4230 res += " Professional";
4235 // Test for the server type.
4237 else if (osvi.wProductType == VER_NT_SERVER)
4239 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
4241 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
4243 res += " Datacenter Edition";
4245 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4247 res += " Enterprise Edition";
4249 else if (osvi.wSuiteMask == VER_SUITE_BLADE)
4251 res += " Web Edition";
4253 else
4255 res += " Standard Edition";
4259 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
4261 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
4263 res += " Datacenter Server";
4265 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4267 res += " Advanced Server";
4269 else
4271 res += " Server";
4275 else if (osvi.dwMajorVersion <= 4) // Windows NT 4.0
4277 if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4279 res += " Server 4.0, Enterprise Edition";
4281 else
4283 res += " Server 4.0";
4287 #endif // Visual Studio 7 and up
4290 // Test for specific product on Windows NT 4.0 SP5 and earlier
4292 else
4294 HKEY hKey;
4295 #define BUFSIZE 80
4296 char szProductType[BUFSIZE];
4297 DWORD dwBufLen=BUFSIZE;
4298 LONG lRet;
4300 lRet = RegOpenKeyEx(
4301 HKEY_LOCAL_MACHINE,
4302 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
4303 0, KEY_QUERY_VALUE, &hKey);
4304 if (lRet != ERROR_SUCCESS)
4306 return 0;
4309 lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL,
4310 (LPBYTE) szProductType, &dwBufLen);
4312 if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
4314 return 0;
4317 RegCloseKey(hKey);
4319 if (lstrcmpi("WINNT", szProductType) == 0)
4321 res += " Workstation";
4323 if (lstrcmpi("LANMANNT", szProductType) == 0)
4325 res += " Server";
4327 if (lstrcmpi("SERVERNT", szProductType) == 0)
4329 res += " Advanced Server";
4332 res += " ";
4333 sprintf(buffer, "%ld", osvi.dwMajorVersion);
4334 res += buffer;
4335 res += ".";
4336 sprintf(buffer, "%ld", osvi.dwMinorVersion);
4337 res += buffer;
4340 // Display service pack (if any) and build number.
4342 if (osvi.dwMajorVersion == 4 &&
4343 lstrcmpi(osvi.szCSDVersion, "Service Pack 6") == 0)
4345 HKEY hKey;
4346 LONG lRet;
4348 // Test for SP6 versus SP6a.
4350 lRet = RegOpenKeyEx(
4351 HKEY_LOCAL_MACHINE,
4352 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
4353 0, KEY_QUERY_VALUE, &hKey);
4355 if (lRet == ERROR_SUCCESS)
4357 res += " Service Pack 6a (Build ";
4358 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4359 res += buffer;
4360 res += ")";
4362 else // Windows NT 4.0 prior to SP6a
4364 res += " ";
4365 res += osvi.szCSDVersion;
4366 res += " (Build ";
4367 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4368 res += buffer;
4369 res += ")";
4372 RegCloseKey(hKey);
4374 else // Windows NT 3.51 and earlier or Windows 2000 and later
4376 res += " ";
4377 res += osvi.szCSDVersion;
4378 res += " (Build ";
4379 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4380 res += buffer;
4381 res += ")";
4384 break;
4386 // Test for the Windows 95 product family.
4388 case VER_PLATFORM_WIN32_WINDOWS:
4390 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
4392 res += "Microsoft Windows 95";
4393 if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
4395 res += " OSR2";
4399 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
4401 res += "Microsoft Windows 98";
4402 if (osvi.szCSDVersion[1] == 'A')
4404 res += " SE";
4408 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
4410 res += "Microsoft Windows Millennium Edition";
4412 break;
4414 case VER_PLATFORM_WIN32s:
4416 res += "Microsoft Win32s";
4417 break;
4419 #endif
4421 return res;
4424 // ----------------------------------------------------------------------
4425 bool SystemTools::ParseURLProtocol( const kwsys_stl::string& URL,
4426 kwsys_stl::string& protocol,
4427 kwsys_stl::string& dataglom )
4429 // match 0 entire url
4430 // match 1 protocol
4431 // match 2 dataglom following protocol://
4432 kwsys::RegularExpression urlRe( VTK_URL_PROTOCOL_REGEX );
4434 if ( ! urlRe.find( URL ) ) return false;
4436 protocol = urlRe.match( 1 );
4437 dataglom = urlRe.match( 2 );
4439 return true;
4442 // ----------------------------------------------------------------------
4443 bool SystemTools::ParseURL( const kwsys_stl::string& URL,
4444 kwsys_stl::string& protocol,
4445 kwsys_stl::string& username,
4446 kwsys_stl::string& password,
4447 kwsys_stl::string& hostname,
4448 kwsys_stl::string& dataport,
4449 kwsys_stl::string& database )
4451 kwsys::RegularExpression urlRe( VTK_URL_REGEX );
4452 if ( ! urlRe.find( URL ) ) return false;
4454 // match 0 URL
4455 // match 1 protocol
4456 // match 2 mangled user
4457 // match 3 username
4458 // match 4 mangled password
4459 // match 5 password
4460 // match 6 hostname
4461 // match 7 mangled port
4462 // match 8 dataport
4463 // match 9 database name
4465 protocol = urlRe.match( 1 );
4466 username = urlRe.match( 3 );
4467 password = urlRe.match( 5 );
4468 hostname = urlRe.match( 6 );
4469 dataport = urlRe.match( 8 );
4470 database = urlRe.match( 9 );
4472 return true;
4475 // ----------------------------------------------------------------------
4476 // These must NOT be initialized. Default initialization to zero is
4477 // necessary.
4478 unsigned int SystemToolsManagerCount;
4479 SystemToolsTranslationMap *SystemTools::TranslationMap;
4480 SystemToolsTranslationMap *SystemTools::LongPathMap;
4482 // SystemToolsManager manages the SystemTools singleton.
4483 // SystemToolsManager should be included in any translation unit
4484 // that will use SystemTools or that implements the singleton
4485 // pattern. It makes sure that the SystemTools singleton is created
4486 // before and destroyed after all other singletons in CMake.
4488 SystemToolsManager::SystemToolsManager()
4490 if(++SystemToolsManagerCount == 1)
4492 SystemTools::ClassInitialize();
4496 SystemToolsManager::~SystemToolsManager()
4498 if(--SystemToolsManagerCount == 0)
4500 SystemTools::ClassFinalize();
4504 void SystemTools::ClassInitialize()
4506 // Allocate the translation map first.
4507 SystemTools::TranslationMap = new SystemToolsTranslationMap;
4508 SystemTools::LongPathMap = new SystemToolsTranslationMap;
4510 // Add some special translation paths for unix. These are not added
4511 // for windows because drive letters need to be maintained. Also,
4512 // there are not sym-links and mount points on windows anyway.
4513 #if !defined(_WIN32) || defined(__CYGWIN__)
4514 // Work-around an SGI problem by always adding this mapping:
4515 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
4516 // The tmp path is frequently a logical path so always keep it:
4517 SystemTools::AddKeepPath("/tmp/");
4519 // If the current working directory is a logical path then keep the
4520 // logical name.
4521 if(const char* pwd = getenv("PWD"))
4523 char buf[2048];
4524 if(const char* cwd = Getcwd(buf, 2048))
4526 // The current working directory may be a logical path. Find
4527 // the shortest logical path that still produces the correct
4528 // physical path.
4529 kwsys_stl::string cwd_changed;
4530 kwsys_stl::string pwd_changed;
4532 // Test progressively shorter logical-to-physical mappings.
4533 kwsys_stl::string pwd_str = pwd;
4534 kwsys_stl::string cwd_str = cwd;
4535 kwsys_stl::string pwd_path;
4536 Realpath(pwd, pwd_path);
4537 while(cwd_str == pwd_path && cwd_str != pwd_str)
4539 // The current pair of paths is a working logical mapping.
4540 cwd_changed = cwd_str;
4541 pwd_changed = pwd_str;
4543 // Strip off one directory level and see if the logical
4544 // mapping still works.
4545 pwd_str = SystemTools::GetFilenamePath(pwd_str.c_str());
4546 cwd_str = SystemTools::GetFilenamePath(cwd_str.c_str());
4547 Realpath(pwd_str.c_str(), pwd_path);
4550 // Add the translation to keep the logical path name.
4551 if(!cwd_changed.empty() && !pwd_changed.empty())
4553 SystemTools::AddTranslationPath(cwd_changed.c_str(),
4554 pwd_changed.c_str());
4558 #endif
4561 void SystemTools::ClassFinalize()
4563 delete SystemTools::TranslationMap;
4564 delete SystemTools::LongPathMap;
4568 } // namespace KWSYS_NAMESPACE
4570 #if defined(_MSC_VER) && defined(_DEBUG)
4571 # include <crtdbg.h>
4572 # include <stdio.h>
4573 # include <stdlib.h>
4574 namespace KWSYS_NAMESPACE
4577 static int SystemToolsDebugReport(int, char* message, int*)
4579 fprintf(stderr, "%s", message);
4580 fflush(stderr);
4581 return 1; // no further reporting required
4584 void SystemTools::EnableMSVCDebugHook()
4586 if (getenv("DART_TEST_FROM_DART"))
4588 _CrtSetReportHook(SystemToolsDebugReport);
4592 } // namespace KWSYS_NAMESPACE
4593 #else
4594 namespace KWSYS_NAMESPACE
4596 void SystemTools::EnableMSVCDebugHook() {}
4597 } // namespace KWSYS_NAMESPACE
4598 #endif