ENH: use .exe on vms
[cmake.git] / Source / kwsys / SystemTools.cxx
blob13470df9ddad01a11317a0037a8d51bd0714c02c
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/wait.h>
57 #include <sys/ioctl.h>
58 #include <unistd.h>
59 #include <pwd.h>
60 #ifndef __VMS
61 #include <sys/param.h>
62 #include <termios.h>
63 #endif
64 #include <signal.h> /* sigprocmask */
65 #endif
67 // Windows API. Some parts used even on cygwin.
68 #if defined(_WIN32)
69 # include <windows.h>
70 #endif
72 // getpwnam doesn't exist on Windows and Cray Xt3/Catamount
73 // same for TIOCGWINSZ
74 #if defined(_WIN32) || defined (__LIBCATAMOUNT__)
75 # undef HAVE_GETPWNAM
76 # undef HAVE_TTY_INFO
77 #else
78 # define HAVE_GETPWNAM 1
79 # define HAVE_TTY_INFO 1
80 #endif
82 #define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)"
83 #define VTK_URL_REGEX "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/(.+)?"
85 #ifdef _MSC_VER
86 #include <sys/utime.h>
87 #else
88 #include <utime.h>
89 #endif
92 // This is a hack to prevent warnings about these functions being
93 // declared but not referenced.
94 #if defined(__sgi) && !defined(__GNUC__)
95 # include <sys/termios.h>
96 namespace KWSYS_NAMESPACE
98 class SystemToolsHack
100 public:
101 enum
103 Ref1 = sizeof(cfgetospeed(0)),
104 Ref2 = sizeof(cfgetispeed(0)),
105 Ref3 = sizeof(tcgetattr(0, 0)),
106 Ref4 = sizeof(tcsetattr(0, 0, 0)),
107 Ref5 = sizeof(cfsetospeed(0,0)),
108 Ref6 = sizeof(cfsetispeed(0,0))
112 #endif
114 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) ||defined(__BORLANDC__) || defined(__MINGW32__))
115 #include <io.h>
116 #include <direct.h>
117 #define _unlink unlink
118 #endif
120 /* The maximum length of a file name. */
121 #if defined(PATH_MAX)
122 # define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
123 #elif defined(MAXPATHLEN)
124 # define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
125 #else
126 # define KWSYS_SYSTEMTOOLS_MAXPATH 16384
127 #endif
128 #if defined(__WATCOMC__)
129 #include <direct.h>
130 #define _mkdir mkdir
131 #define _rmdir rmdir
132 #define _getcwd getcwd
133 #define _chdir chdir
134 #endif
136 #if defined(__HAIKU__)
137 #include <os/kernel/OS.h>
138 #include <os/storage/Path.h>
139 #endif
141 #if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
142 #include <be/kernel/OS.h>
143 #include <be/storage/Path.h>
145 // BeOS 5 doesn't have usleep(), but it has snooze(), which is identical.
146 static inline void usleep(unsigned int msec)
148 ::snooze(msec);
151 // BeOS 5 also doesn't have realpath(), but its C++ API offers something close.
152 static inline char *realpath(const char *path, char *resolved_path)
154 const size_t maxlen = KWSYS_SYSTEMTOOLS_MAXPATH;
155 snprintf(resolved_path, maxlen, "%s", path);
156 BPath normalized(resolved_path, NULL, true);
157 const char *resolved = normalized.Path();
158 if (resolved != NULL) // NULL == No such file.
160 if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen)
162 return resolved_path;
165 return NULL; // something went wrong.
167 #endif
169 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
170 inline int Mkdir(const char* dir)
172 return _mkdir(dir);
174 inline int Rmdir(const char* dir)
176 return _rmdir(dir);
178 inline const char* Getcwd(char* buf, unsigned int len)
180 const char* ret = _getcwd(buf, len);
181 if(!ret)
183 fprintf(stderr, "No current working directory.\n");
184 abort();
186 // make sure the drive letter is capital
187 if(strlen(buf) > 1 && buf[1] == ':')
189 buf[0] = toupper(buf[0]);
191 return ret;
193 inline int Chdir(const char* dir)
195 #if defined(__BORLANDC__)
196 return chdir(dir);
197 #else
198 return _chdir(dir);
199 #endif
201 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
203 char *ptemp;
204 char fullpath[MAX_PATH];
205 if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) )
207 resolved_path = fullpath;
208 KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
210 else
212 resolved_path = path;
215 #else
216 #include <sys/types.h>
217 #include <fcntl.h>
218 #include <unistd.h>
219 inline int Mkdir(const char* dir)
221 return mkdir(dir, 00777);
223 inline int Rmdir(const char* dir)
225 return rmdir(dir);
227 inline const char* Getcwd(char* buf, unsigned int len)
229 const char* ret = getcwd(buf, len);
230 if(!ret)
232 fprintf(stderr, "No current working directory\n");
233 abort();
235 return ret;
238 inline int Chdir(const char* dir)
240 return chdir(dir);
242 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
244 char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
246 char *ret = realpath(path, resolved_name);
247 if(ret)
249 resolved_path = ret;
251 else
253 // if path resolution fails, return what was passed in
254 resolved_path = path;
257 #endif
259 #if !defined(_WIN32) && defined(__COMO__)
260 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
261 extern "C"
263 extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
264 extern int pclose (FILE *__stream) __THROW;
265 extern char *realpath (__const char *__restrict __name,
266 char *__restrict __resolved) __THROW;
267 extern char *strdup (__const char *__s) __THROW;
268 extern int putenv (char *__string) __THROW;
270 #endif
272 /* Implement floattime() for various platforms */
273 // Taken from Python 2.1.3
275 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
276 # include <sys/timeb.h>
277 # define HAVE_FTIME
278 # if defined( __BORLANDC__)
279 # define FTIME ftime
280 # define TIMEB timeb
281 # else // Visual studio?
282 # define FTIME _ftime
283 # define TIMEB _timeb
284 # endif
285 #elif defined( __CYGWIN__ ) || defined( __linux__ )
286 # include <sys/time.h>
287 # include <time.h>
288 # define HAVE_GETTIMEOFDAY
289 #endif
291 namespace KWSYS_NAMESPACE
294 class SystemToolsTranslationMap :
295 public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
300 double
301 SystemTools::GetTime(void)
303 /* There are three ways to get the time:
304 (1) gettimeofday() -- resolution in microseconds
305 (2) ftime() -- resolution in milliseconds
306 (3) time() -- resolution in seconds
307 In all cases the return value is a float in seconds.
308 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
309 fail, so we fall back on ftime() or time().
310 Note: clock resolution does not imply clock accuracy! */
311 #ifdef HAVE_GETTIMEOFDAY
313 struct timeval t;
314 #ifdef GETTIMEOFDAY_NO_TZ
315 if (gettimeofday(&t) == 0)
316 #else /* !GETTIMEOFDAY_NO_TZ */
317 if (gettimeofday(&t, static_cast<struct timezone *>(NULL)) == 0)
318 #endif /* !GETTIMEOFDAY_NO_TZ */
319 return static_cast<double>(t.tv_sec) +
320 static_cast<double>(t.tv_usec)*0.000001;
322 #endif /* !HAVE_GETTIMEOFDAY */
324 #if defined(HAVE_FTIME)
325 struct TIMEB t;
326 ::FTIME(&t);
327 return static_cast<double>(t.time) +
328 static_cast<double>(t.millitm) * static_cast<double>(0.001);
329 #else /* !HAVE_FTIME */
330 time_t secs;
331 time(&secs);
332 return static_cast<double>(secs);
333 #endif /* !HAVE_FTIME */
337 // adds the elements of the env variable path to the arg passed in
338 void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
340 #if defined(_WIN32) && !defined(__CYGWIN__)
341 const char* pathSep = ";";
342 #else
343 const char* pathSep = ":";
344 #endif
345 if(!env)
347 env = "PATH";
349 const char* cpathEnv = SystemTools::GetEnv(env);
350 if ( !cpathEnv )
352 return;
355 kwsys_stl::string pathEnv = cpathEnv;
357 // A hack to make the below algorithm work.
358 if(pathEnv[pathEnv.length()-1] != ':')
360 pathEnv += pathSep;
362 kwsys_stl::string::size_type start =0;
363 bool done = false;
364 while(!done)
366 kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
367 if(endpos != kwsys_stl::string::npos)
369 kwsys_stl::string convertedPath;
370 Realpath(pathEnv.substr(start, endpos-start).c_str(), convertedPath);
371 path.push_back(convertedPath);
372 start = endpos+1;
374 else
376 done = true;
379 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
380 i != path.end(); ++i)
382 SystemTools::ConvertToUnixSlashes(*i);
386 const char* SystemTools::GetEnv(const char* key)
388 return getenv(key);
391 bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
393 const char* v = getenv(key);
394 if(v)
396 result = v;
397 return true;
399 else
401 return false;
405 class kwsysDeletingCharVector : public kwsys_stl::vector<char*>
407 public:
408 ~kwsysDeletingCharVector();
411 kwsysDeletingCharVector::~kwsysDeletingCharVector()
413 for(kwsys_stl::vector<char*>::iterator i = this->begin();
414 i != this->end(); ++i)
416 delete []*i;
419 bool SystemTools::PutEnv(const char* value)
421 static kwsysDeletingCharVector localEnvironment;
422 char* envVar = new char[strlen(value)+1];
423 strcpy(envVar, value);
424 int ret = putenv(envVar);
425 // save the pointer in the static vector so that it can
426 // be deleted on exit
427 localEnvironment.push_back(envVar);
428 return ret == 0;
432 const char* SystemTools::GetExecutableExtension()
434 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS)
435 return ".exe";
436 #else
437 return "";
438 #endif
442 bool SystemTools::MakeDirectory(const char* path)
444 if(!path)
446 return false;
448 if(SystemTools::FileExists(path))
450 return true;
452 kwsys_stl::string dir = path;
453 if(dir.size() == 0)
455 return false;
457 SystemTools::ConvertToUnixSlashes(dir);
459 kwsys_stl::string::size_type pos = dir.find(':');
460 if(pos == kwsys_stl::string::npos)
462 pos = 0;
464 kwsys_stl::string topdir;
465 while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
467 topdir = dir.substr(0, pos);
468 Mkdir(topdir.c_str());
469 pos++;
471 if(dir[dir.size()-1] == '/')
473 topdir = dir.substr(0, dir.size());
475 else
477 topdir = dir;
479 if(Mkdir(topdir.c_str()) != 0)
481 // There is a bug in the Borland Run time library which makes MKDIR
482 // return EACCES when it should return EEXISTS
483 // if it is some other error besides directory exists
484 // then return false
485 if( (errno != EEXIST)
486 #ifdef __BORLANDC__
487 && (errno != EACCES)
488 #endif
491 return false;
494 return true;
498 // replace replace with with as many times as it shows up in source.
499 // write the result into source.
500 void SystemTools::ReplaceString(kwsys_stl::string& source,
501 const char* replace,
502 const char* with)
504 const char *src = source.c_str();
505 char *searchPos = const_cast<char *>(strstr(src,replace));
507 // get out quick if string is not found
508 if (!searchPos)
510 return;
513 // perform replacements until done
514 size_t replaceSize = strlen(replace);
515 // do while hangs if replaceSize is 0
516 if(replaceSize == 0)
518 return;
520 char *orig = strdup(src);
521 char *currentPos = orig;
522 searchPos = searchPos - src + orig;
524 // initialize the result
525 source.erase(source.begin(),source.end());
528 *searchPos = '\0';
529 source += currentPos;
530 currentPos = searchPos + replaceSize;
531 // replace
532 source += with;
533 searchPos = strstr(currentPos,replace);
535 while (searchPos);
537 // copy any trailing text
538 source += currentPos;
539 free(orig);
542 #if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
543 # define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
544 # define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
545 #else
546 # define KWSYS_ST_KEY_WOW64_32KEY 0x0200
547 # define KWSYS_ST_KEY_WOW64_64KEY 0x0100
548 #endif
550 #if defined(_WIN32) && !defined(__CYGWIN__)
551 static DWORD SystemToolsMakeRegistryMode(DWORD mode,
552 SystemTools::KeyWOW64 view)
554 if(view == SystemTools::KeyWOW64_32)
556 return mode | KWSYS_ST_KEY_WOW64_32KEY;
558 else if(view == SystemTools::KeyWOW64_64)
560 return mode | KWSYS_ST_KEY_WOW64_64KEY;
562 return mode;
564 #endif
566 // Read a registry value.
567 // Example :
568 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
569 // => will return the data of the "default" value of the key
570 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
571 // => will return the data of the "Root" value of the key
573 #if defined(_WIN32) && !defined(__CYGWIN__)
574 bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
575 KeyWOW64 view)
577 bool valueset = false;
578 kwsys_stl::string primary = key;
579 kwsys_stl::string second;
580 kwsys_stl::string valuename;
582 size_t start = primary.find("\\");
583 if (start == kwsys_stl::string::npos)
585 return false;
588 size_t valuenamepos = primary.find(";");
589 if (valuenamepos != kwsys_stl::string::npos)
591 valuename = primary.substr(valuenamepos+1);
594 second = primary.substr(start+1, valuenamepos-start-1);
595 primary = primary.substr(0, start);
597 HKEY primaryKey = HKEY_CURRENT_USER;
598 if (primary == "HKEY_CURRENT_USER")
600 primaryKey = HKEY_CURRENT_USER;
602 if (primary == "HKEY_CURRENT_CONFIG")
604 primaryKey = HKEY_CURRENT_CONFIG;
606 if (primary == "HKEY_CLASSES_ROOT")
608 primaryKey = HKEY_CLASSES_ROOT;
610 if (primary == "HKEY_LOCAL_MACHINE")
612 primaryKey = HKEY_LOCAL_MACHINE;
614 if (primary == "HKEY_USERS")
616 primaryKey = HKEY_USERS;
619 HKEY hKey;
620 if(RegOpenKeyEx(primaryKey,
621 second.c_str(),
623 SystemToolsMakeRegistryMode(KEY_READ, view),
624 &hKey) != ERROR_SUCCESS)
626 return false;
628 else
630 DWORD dwType, dwSize;
631 dwSize = 1023;
632 char data[1024];
633 if(RegQueryValueEx(hKey,
634 (LPTSTR)valuename.c_str(),
635 NULL,
636 &dwType,
637 (BYTE *)data,
638 &dwSize) == ERROR_SUCCESS)
640 if (dwType == REG_SZ)
642 value = data;
643 valueset = true;
645 else if (dwType == REG_EXPAND_SZ)
647 char expanded[1024];
648 DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]);
649 if(ExpandEnvironmentStrings(data, expanded, dwExpandedSize))
651 value = expanded;
652 valueset = true;
657 RegCloseKey(hKey);
660 return valueset;
662 #else
663 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
664 KeyWOW64)
666 return false;
668 #endif
671 // Write a registry value.
672 // Example :
673 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
674 // => will set the data of the "default" value of the key
675 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
676 // => will set the data of the "Root" value of the key
678 #if defined(_WIN32) && !defined(__CYGWIN__)
679 bool SystemTools::WriteRegistryValue(const char *key, const char *value,
680 KeyWOW64 view)
682 kwsys_stl::string primary = key;
683 kwsys_stl::string second;
684 kwsys_stl::string valuename;
686 size_t start = primary.find("\\");
687 if (start == kwsys_stl::string::npos)
689 return false;
692 size_t valuenamepos = primary.find(";");
693 if (valuenamepos != kwsys_stl::string::npos)
695 valuename = primary.substr(valuenamepos+1);
698 second = primary.substr(start+1, valuenamepos-start-1);
699 primary = primary.substr(0, start);
701 HKEY primaryKey = HKEY_CURRENT_USER;
702 if (primary == "HKEY_CURRENT_USER")
704 primaryKey = HKEY_CURRENT_USER;
706 if (primary == "HKEY_CURRENT_CONFIG")
708 primaryKey = HKEY_CURRENT_CONFIG;
710 if (primary == "HKEY_CLASSES_ROOT")
712 primaryKey = HKEY_CLASSES_ROOT;
714 if (primary == "HKEY_LOCAL_MACHINE")
716 primaryKey = HKEY_LOCAL_MACHINE;
718 if (primary == "HKEY_USERS")
720 primaryKey = HKEY_USERS;
723 HKEY hKey;
724 DWORD dwDummy;
725 if(RegCreateKeyEx(primaryKey,
726 second.c_str(),
729 REG_OPTION_NON_VOLATILE,
730 SystemToolsMakeRegistryMode(KEY_WRITE, view),
731 NULL,
732 &hKey,
733 &dwDummy) != ERROR_SUCCESS)
735 return false;
738 if(RegSetValueEx(hKey,
739 (LPTSTR)valuename.c_str(),
741 REG_SZ,
742 (CONST BYTE *)value,
743 (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
745 return true;
747 return false;
749 #else
750 bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
752 return false;
754 #endif
756 // Delete a registry value.
757 // Example :
758 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
759 // => will delete the data of the "default" value of the key
760 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
761 // => will delete the data of the "Root" value of the key
763 #if defined(_WIN32) && !defined(__CYGWIN__)
764 bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
766 kwsys_stl::string primary = key;
767 kwsys_stl::string second;
768 kwsys_stl::string valuename;
770 size_t start = primary.find("\\");
771 if (start == kwsys_stl::string::npos)
773 return false;
776 size_t valuenamepos = primary.find(";");
777 if (valuenamepos != kwsys_stl::string::npos)
779 valuename = primary.substr(valuenamepos+1);
782 second = primary.substr(start+1, valuenamepos-start-1);
783 primary = primary.substr(0, start);
785 HKEY primaryKey = HKEY_CURRENT_USER;
786 if (primary == "HKEY_CURRENT_USER")
788 primaryKey = HKEY_CURRENT_USER;
790 if (primary == "HKEY_CURRENT_CONFIG")
792 primaryKey = HKEY_CURRENT_CONFIG;
794 if (primary == "HKEY_CLASSES_ROOT")
796 primaryKey = HKEY_CLASSES_ROOT;
798 if (primary == "HKEY_LOCAL_MACHINE")
800 primaryKey = HKEY_LOCAL_MACHINE;
802 if (primary == "HKEY_USERS")
804 primaryKey = HKEY_USERS;
807 HKEY hKey;
808 if(RegOpenKeyEx(primaryKey,
809 second.c_str(),
811 SystemToolsMakeRegistryMode(KEY_WRITE, view),
812 &hKey) != ERROR_SUCCESS)
814 return false;
816 else
818 if(RegDeleteValue(hKey,
819 (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
821 RegCloseKey(hKey);
822 return true;
825 return false;
827 #else
828 bool SystemTools::DeleteRegistryValue(const char *, KeyWOW64)
830 return false;
832 #endif
834 bool SystemTools::SameFile(const char* file1, const char* file2)
836 #ifdef _WIN32
837 HANDLE hFile1, hFile2;
839 hFile1 = CreateFile( file1,
840 GENERIC_READ,
841 FILE_SHARE_READ ,
842 NULL,
843 OPEN_EXISTING,
844 FILE_FLAG_BACKUP_SEMANTICS,
845 NULL
847 hFile2 = CreateFile( file2,
848 GENERIC_READ,
849 FILE_SHARE_READ,
850 NULL,
851 OPEN_EXISTING,
852 FILE_FLAG_BACKUP_SEMANTICS,
853 NULL
855 if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
857 if(hFile1 != INVALID_HANDLE_VALUE)
859 CloseHandle(hFile1);
861 if(hFile2 != INVALID_HANDLE_VALUE)
863 CloseHandle(hFile2);
865 return false;
868 BY_HANDLE_FILE_INFORMATION fiBuf1;
869 BY_HANDLE_FILE_INFORMATION fiBuf2;
870 GetFileInformationByHandle( hFile1, &fiBuf1 );
871 GetFileInformationByHandle( hFile2, &fiBuf2 );
872 CloseHandle(hFile1);
873 CloseHandle(hFile2);
874 return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
875 fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
876 fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
877 #else
878 struct stat fileStat1, fileStat2;
879 if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
881 // see if the files are the same file
882 // check the device inode and size
883 if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
884 memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
885 fileStat2.st_size == fileStat1.st_size
888 return true;
891 return false;
892 #endif
896 // return true if the file exists
897 bool SystemTools::FileExists(const char* filename, bool isFile)
899 #ifdef _MSC_VER
900 # define access _access
901 #endif
902 #ifndef R_OK
903 # define R_OK 04
904 #endif
906 #ifdef __SYLLABLE__
907 if ((filename !=0) && (*filename == 0))
909 return false;
911 #endif
913 if ( access(filename, R_OK) != 0 )
915 return false;
917 else
919 // If isFile is set return not FileIsDirectory,
920 // so this will only be true if it is a file
921 if(isFile)
923 return !SystemTools::FileIsDirectory(filename);
925 return true;
929 bool SystemTools::Touch(const char* filename, bool create)
931 if(create && !SystemTools::FileExists(filename))
933 FILE* file = fopen(filename, "a+b");
934 if(file)
936 fclose(file);
937 return true;
939 return false;
941 #ifdef _MSC_VER
942 #define utime _utime
943 #define utimbuf _utimbuf
944 #endif
945 struct stat fromStat;
946 if(stat(filename, &fromStat) < 0)
948 return false;
950 struct utimbuf buf;
951 buf.actime = fromStat.st_atime;
952 buf.modtime = static_cast<time_t>(SystemTools::GetTime());
953 if(utime(filename, &buf) < 0)
955 return false;
957 return true;
960 bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
961 int* result)
963 // Default to same time.
964 *result = 0;
965 #if !defined(_WIN32) || defined(__CYGWIN__)
966 // POSIX version. Use stat function to get file modification time.
967 struct stat s1;
968 if(stat(f1, &s1) != 0)
970 return false;
972 struct stat s2;
973 if(stat(f2, &s2) != 0)
975 return false;
977 # if KWSYS_STAT_HAS_ST_MTIM
978 // Compare using nanosecond resolution.
979 if(s1.st_mtim.tv_sec < s2.st_mtim.tv_sec)
981 *result = -1;
983 else if(s1.st_mtim.tv_sec > s2.st_mtim.tv_sec)
985 *result = 1;
987 else if(s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec)
989 *result = -1;
991 else if(s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec)
993 *result = 1;
995 # else
996 // Compare using 1 second resolution.
997 if(s1.st_mtime < s2.st_mtime)
999 *result = -1;
1001 else if(s1.st_mtime > s2.st_mtime)
1003 *result = 1;
1005 # endif
1006 #else
1007 // Windows version. Get the modification time from extended file attributes.
1008 WIN32_FILE_ATTRIBUTE_DATA f1d;
1009 WIN32_FILE_ATTRIBUTE_DATA f2d;
1010 if(!GetFileAttributesEx(f1, GetFileExInfoStandard, &f1d))
1012 return false;
1014 if(!GetFileAttributesEx(f2, GetFileExInfoStandard, &f2d))
1016 return false;
1019 // Compare the file times using resolution provided by system call.
1020 *result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime);
1021 #endif
1022 return true;
1026 // Return a capitalized string (i.e the first letter is uppercased, all other
1027 // are lowercased)
1028 kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s)
1030 kwsys_stl::string n;
1031 if(s.size() == 0)
1033 return n;
1035 n.resize(s.size());
1036 n[0] = static_cast<kwsys_stl::string::value_type>(toupper(s[0]));
1037 for (size_t i = 1; i < s.size(); i++)
1039 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1041 return n;
1044 // Return capitalized words
1045 kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s)
1047 kwsys_stl::string n(s);
1048 for (size_t i = 0; i < s.size(); i++)
1050 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1051 // MS has an assert that will fail if s[i] < 0; setting
1052 // LC_CTYPE using setlocale() does *not* help. Painful.
1053 if ((int)s[i] >= 0 && isalpha(s[i]) &&
1054 (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1]))))
1055 #else
1056 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
1057 #endif
1059 n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
1062 return n;
1065 // Return uncapitalized words
1066 kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s)
1068 kwsys_stl::string n(s);
1069 for (size_t i = 0; i < s.size(); i++)
1071 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1072 // MS has an assert that will fail if s[i] < 0; setting
1073 // LC_CTYPE using setlocale() does *not* help. Painful.
1074 if ((int)s[i] >= 0 && isalpha(s[i]) &&
1075 (i == 0 || ((int)s[i - 1] >= 0 && isspace(s[i - 1]))))
1076 #else
1077 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
1078 #endif
1080 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1083 return n;
1086 // only works for words with at least two letters
1087 kwsys_stl::string SystemTools::AddSpaceBetweenCapitalizedWords(
1088 const kwsys_stl::string& s)
1090 kwsys_stl::string n;
1091 if (s.size())
1093 n.reserve(s.size());
1094 n += s[0];
1095 for (size_t i = 1; i < s.size(); i++)
1097 if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1]))
1099 n += ' ';
1101 n += s[i];
1104 return n;
1107 char* SystemTools::AppendStrings(const char* str1, const char* str2)
1109 if (!str1)
1111 return SystemTools::DuplicateString(str2);
1113 if (!str2)
1115 return SystemTools::DuplicateString(str1);
1117 size_t len1 = strlen(str1);
1118 char *newstr = new char[len1 + strlen(str2) + 1];
1119 if (!newstr)
1121 return 0;
1123 strcpy(newstr, str1);
1124 strcat(newstr + len1, str2);
1125 return newstr;
1128 char* SystemTools::AppendStrings(
1129 const char* str1, const char* str2, const char* str3)
1131 if (!str1)
1133 return SystemTools::AppendStrings(str2, str3);
1135 if (!str2)
1137 return SystemTools::AppendStrings(str1, str3);
1139 if (!str3)
1141 return SystemTools::AppendStrings(str1, str2);
1144 size_t len1 = strlen(str1), len2 = strlen(str2);
1145 char *newstr = new char[len1 + len2 + strlen(str3) + 1];
1146 if (!newstr)
1148 return 0;
1150 strcpy(newstr, str1);
1151 strcat(newstr + len1, str2);
1152 strcat(newstr + len1 + len2, str3);
1153 return newstr;
1156 // Return a lower case string
1157 kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s)
1159 kwsys_stl::string n;
1160 n.resize(s.size());
1161 for (size_t i = 0; i < s.size(); i++)
1163 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
1165 return n;
1168 // Return a lower case string
1169 kwsys_stl::string SystemTools::UpperCase(const kwsys_stl::string& s)
1171 kwsys_stl::string n;
1172 n.resize(s.size());
1173 for (size_t i = 0; i < s.size(); i++)
1175 n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
1177 return n;
1180 // Count char in string
1181 size_t SystemTools::CountChar(const char* str, char c)
1183 size_t count = 0;
1185 if (str)
1187 while (*str)
1189 if (*str == c)
1191 ++count;
1193 ++str;
1196 return count;
1199 // Remove chars in string
1200 char* SystemTools::RemoveChars(const char* str, const char *toremove)
1202 if (!str)
1204 return NULL;
1206 char *clean_str = new char [strlen(str) + 1];
1207 char *ptr = clean_str;
1208 while (*str)
1210 const char *str2 = toremove;
1211 while (*str2 && *str != *str2)
1213 ++str2;
1215 if (!*str2)
1217 *ptr++ = *str;
1219 ++str;
1221 *ptr = '\0';
1222 return clean_str;
1225 // Remove chars in string
1226 char* SystemTools::RemoveCharsButUpperHex(const char* str)
1228 if (!str)
1230 return 0;
1232 char *clean_str = new char [strlen(str) + 1];
1233 char *ptr = clean_str;
1234 while (*str)
1236 if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'F'))
1238 *ptr++ = *str;
1240 ++str;
1242 *ptr = '\0';
1243 return clean_str;
1246 // Replace chars in string
1247 char* SystemTools::ReplaceChars(char* str, const char *toreplace, char replacement)
1249 if (str)
1251 char *ptr = str;
1252 while (*ptr)
1254 const char *ptr2 = toreplace;
1255 while (*ptr2)
1257 if (*ptr == *ptr2)
1259 *ptr = replacement;
1261 ++ptr2;
1263 ++ptr;
1266 return str;
1269 // Returns if string starts with another string
1270 bool SystemTools::StringStartsWith(const char* str1, const char* str2)
1272 if (!str1 || !str2)
1274 return false;
1276 size_t len1 = strlen(str1), len2 = strlen(str2);
1277 return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false;
1280 // Returns if string ends with another string
1281 bool SystemTools::StringEndsWith(const char* str1, const char* str2)
1283 if (!str1 || !str2)
1285 return false;
1287 size_t len1 = strlen(str1), len2 = strlen(str2);
1288 return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true : false;
1291 // Returns a pointer to the last occurence of str2 in str1
1292 const char* SystemTools::FindLastString(const char* str1, const char* str2)
1294 if (!str1 || !str2)
1296 return NULL;
1299 size_t len1 = strlen(str1), len2 = strlen(str2);
1300 if (len1 >= len2)
1302 const char *ptr = str1 + len1 - len2;
1305 if (!strncmp(ptr, str2, len2))
1307 return ptr;
1309 } while (ptr-- != str1);
1312 return NULL;
1315 // Duplicate string
1316 char* SystemTools::DuplicateString(const char* str)
1318 if (str)
1320 char *newstr = new char [strlen(str) + 1];
1321 return strcpy(newstr, str);
1323 return NULL;
1326 // Return a cropped string
1327 kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
1328 size_t max_len)
1330 if (!s.size() || max_len == 0 || max_len >= s.size())
1332 return s;
1335 kwsys_stl::string n;
1336 n.reserve(max_len);
1338 size_t middle = max_len / 2;
1340 n += s.substr(0, middle);
1341 n += s.substr(s.size() - (max_len - middle), kwsys_stl::string::npos);
1343 if (max_len > 2)
1345 n[middle] = '.';
1346 if (max_len > 3)
1348 n[middle - 1] = '.';
1349 if (max_len > 4)
1351 n[middle + 1] = '.';
1356 return n;
1359 //----------------------------------------------------------------------------
1360 kwsys_stl::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
1362 kwsys_stl::string path = p;
1363 kwsys_stl::vector<kwsys::String> paths;
1364 if(isPath && path[0] == '/')
1366 path.erase(path.begin());
1367 paths.push_back("/");
1369 kwsys_stl::string::size_type pos1 = 0;
1370 kwsys_stl::string::size_type pos2 = path.find(sep, pos1+1);
1371 while(pos2 != kwsys_stl::string::npos)
1373 paths.push_back(path.substr(pos1, pos2-pos1));
1374 pos1 = pos2+1;
1375 pos2 = path.find(sep, pos1+1);
1377 paths.push_back(path.substr(pos1, pos2-pos1));
1379 return paths;
1382 //----------------------------------------------------------------------------
1383 int SystemTools::EstimateFormatLength(const char *format, va_list ap)
1385 if (!format)
1387 return 0;
1390 // Quick-hack attempt at estimating the length of the string.
1391 // Should never under-estimate.
1393 // Start with the length of the format string itself.
1395 size_t length = strlen(format);
1397 // Increase the length for every argument in the format.
1399 const char* cur = format;
1400 while(*cur)
1402 if(*cur++ == '%')
1404 // Skip "%%" since it doesn't correspond to a va_arg.
1405 if(*cur != '%')
1407 while(!int(isalpha(*cur)))
1409 ++cur;
1411 switch (*cur)
1413 case 's':
1415 // Check the length of the string.
1416 char* s = va_arg(ap, char*);
1417 if(s)
1419 length += strlen(s);
1421 } break;
1422 case 'e':
1423 case 'f':
1424 case 'g':
1426 // Assume the argument contributes no more than 64 characters.
1427 length += 64;
1429 // Eat the argument.
1430 static_cast<void>(va_arg(ap, double));
1431 } break;
1432 default:
1434 // Assume the argument contributes no more than 64 characters.
1435 length += 64;
1437 // Eat the argument.
1438 static_cast<void>(va_arg(ap, int));
1439 } break;
1443 // Move past the characters just tested.
1444 ++cur;
1448 return static_cast<int>(length);
1451 kwsys_stl::string SystemTools::EscapeChars(
1452 const char *str,
1453 const char *chars_to_escape,
1454 char escape_char)
1456 kwsys_stl::string n;
1457 if (str)
1459 if (!chars_to_escape | !*chars_to_escape)
1461 n.append(str);
1463 else
1465 n.reserve(strlen(str));
1466 while (*str)
1468 const char *ptr = chars_to_escape;
1469 while (*ptr)
1471 if (*str == *ptr)
1473 n += escape_char;
1474 break;
1476 ++ptr;
1478 n += *str;
1479 ++str;
1483 return n;
1486 #ifdef __VMS
1487 static void ConvertVMSToUnix(kwsys_stl::string& path)
1489 kwsys_stl::string::size_type rootEnd = path.find(":[");
1490 kwsys_stl::string::size_type pathEnd = path.find("]");
1491 if(rootEnd != path.npos)
1493 kwsys_stl::string root = path.substr(0, rootEnd);
1494 kwsys_stl::string pathPart = path.substr(rootEnd+2, pathEnd - rootEnd-2);
1495 const char* pathCString = pathPart.c_str();
1496 const char* pos0 = pathCString;
1497 for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos )
1499 if ( *pos0 == '.' )
1501 pathPart[pos] = '/';
1503 pos0 ++;
1505 path = "/"+ root + "/" + pathPart;
1508 #endif
1510 // convert windows slashes to unix slashes
1511 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
1513 const char* pathCString = path.c_str();
1514 bool hasDoubleSlash = false;
1515 #ifdef __VMS
1516 ConvertVMSToUnix(path);
1517 #else
1518 const char* pos0 = pathCString;
1519 const char* pos1 = pathCString+1;
1520 for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos )
1522 // make sure we don't convert an escaped space to a unix slash
1523 if ( *pos0 == '\\' && *pos1 != ' ' )
1525 path[pos] = '/';
1528 // Also, reuse the loop to check for slash followed by another slash
1529 if (*pos1 == '/' && *(pos1+1) == '/' && !hasDoubleSlash)
1531 #ifdef _WIN32
1532 // However, on windows if the first characters are both slashes,
1533 // then keep them that way, so that network paths can be handled.
1534 if ( pos > 0)
1536 hasDoubleSlash = true;
1538 #else
1539 hasDoubleSlash = true;
1540 #endif
1543 pos0 ++;
1544 pos1 ++;
1547 if ( hasDoubleSlash )
1549 SystemTools::ReplaceString(path, "//", "/");
1551 #endif
1552 // remove any trailing slash
1553 if(!path.empty())
1555 // if there is a tilda ~ then replace it with HOME
1556 pathCString = path.c_str();
1557 if(pathCString[0] == '~' && (pathCString[1] == '/' || pathCString[1] == '\0'))
1559 const char* homeEnv = SystemTools::GetEnv("HOME");
1560 if (homeEnv)
1562 path.replace(0,1,homeEnv);
1565 #ifdef HAVE_GETPWNAM
1566 else if(pathCString[0] == '~')
1568 kwsys_stl::string::size_type idx = path.find_first_of("/\0");
1569 kwsys_stl::string user = path.substr(1, idx-1);
1570 passwd* pw = getpwnam(user.c_str());
1571 if(pw)
1573 path.replace(0, idx, pw->pw_dir);
1576 #endif
1577 // remove trailing slash if the path is more than
1578 // a single /
1579 pathCString = path.c_str();
1580 if(path.size() > 1 && *(pathCString+(path.size()-1)) == '/')
1582 // if it is c:/ then do not remove the trailing slash
1583 if(!((path.size() == 3 && pathCString[1] == ':')))
1585 path = path.substr(0, path.size()-1);
1591 // change // to /, and escape any spaces in the path
1592 kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
1594 kwsys_stl::string ret = path;
1596 // remove // except at the beginning might be a cygwin drive
1597 kwsys_stl::string::size_type pos=0;
1598 while((pos = ret.find("//", pos)) != kwsys_stl::string::npos)
1600 ret.erase(pos, 1);
1602 // escape spaces and () in the path
1603 if(ret.find_first_of(" ") != kwsys_stl::string::npos)
1605 kwsys_stl::string result = "";
1606 char lastch = 1;
1607 for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
1609 // if it is already escaped then don't try to escape it again
1610 if((*ch == ' ') && lastch != '\\')
1612 result += '\\';
1614 result += *ch;
1615 lastch = *ch;
1617 ret = result;
1619 return ret;
1622 kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path)
1624 #if defined(_WIN32) && !defined(__CYGWIN__)
1625 return SystemTools::ConvertToWindowsOutputPath(path);
1626 #else
1627 return SystemTools::ConvertToUnixOutputPath(path);
1628 #endif
1631 // remove double slashes not at the start
1632 kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path)
1634 kwsys_stl::string ret;
1635 // make it big enough for all of path and double quotes
1636 ret.reserve(strlen(path)+3);
1637 // put path into the string
1638 ret.assign(path);
1639 ret = path;
1640 kwsys_stl::string::size_type pos = 0;
1641 // first convert all of the slashes
1642 while((pos = ret.find('/', pos)) != kwsys_stl::string::npos)
1644 ret[pos] = '\\';
1645 pos++;
1647 // check for really small paths
1648 if(ret.size() < 2)
1650 return ret;
1652 // now clean up a bit and remove double slashes
1653 // Only if it is not the first position in the path which is a network
1654 // path on windows
1655 pos = 1; // start at position 1
1656 if(ret[0] == '\"')
1658 pos = 2; // if the string is already quoted then start at 2
1659 if(ret.size() < 3)
1661 return ret;
1664 while((pos = ret.find("\\\\", pos)) != kwsys_stl::string::npos)
1666 ret.erase(pos, 1);
1668 // now double quote the path if it has spaces in it
1669 // and is not already double quoted
1670 if(ret.find(' ') != kwsys_stl::string::npos
1671 && ret[0] != '\"')
1673 ret.insert(static_cast<kwsys_stl::string::size_type>(0),
1674 static_cast<kwsys_stl::string::size_type>(1), '\"');
1675 ret.append(1, '\"');
1677 return ret;
1680 bool SystemTools::CopyFileIfDifferent(const char* source,
1681 const char* destination,
1682 bool copyPermissions)
1684 // special check for a destination that is a directory
1685 // FilesDiffer does not handle file to directory compare
1686 if(SystemTools::FileIsDirectory(destination))
1688 kwsys_stl::string new_destination = destination;
1689 SystemTools::ConvertToUnixSlashes(new_destination);
1690 new_destination += '/';
1691 kwsys_stl::string source_name = source;
1692 new_destination += SystemTools::GetFilenameName(source_name);
1693 if(SystemTools::FilesDiffer(source, new_destination.c_str()))
1695 return SystemTools::CopyFileAlways(source, destination,
1696 copyPermissions);
1698 else
1700 // the files are the same so the copy is done return
1701 // true
1702 return true;
1705 // source and destination are files so do a copy if they
1706 // are different
1707 if(SystemTools::FilesDiffer(source, destination))
1709 return SystemTools::CopyFileAlways(source, destination, copyPermissions);
1711 // at this point the files must be the same so return true
1712 return true;
1715 #define KWSYS_ST_BUFFER 4096
1717 bool SystemTools::FilesDiffer(const char* source,
1718 const char* destination)
1720 struct stat statSource;
1721 if (stat(source, &statSource) != 0)
1723 return true;
1726 struct stat statDestination;
1727 if (stat(destination, &statDestination) != 0)
1729 return true;
1732 if(statSource.st_size != statDestination.st_size)
1734 return true;
1737 if(statSource.st_size == 0)
1739 return false;
1742 #if defined(_WIN32) || defined(__CYGWIN__)
1743 kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
1744 kwsys_ios::ios::in));
1745 kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
1746 kwsys_ios::ios::in));
1747 #else
1748 kwsys_ios::ifstream finSource(source);
1749 kwsys_ios::ifstream finDestination(destination);
1750 #endif
1751 if(!finSource || !finDestination)
1753 return true;
1756 // Compare the files a block at a time.
1757 char source_buf[KWSYS_ST_BUFFER];
1758 char dest_buf[KWSYS_ST_BUFFER];
1759 off_t nleft = statSource.st_size;
1760 while(nleft > 0)
1762 // Read a block from each file.
1763 kwsys_ios::streamsize nnext = (nleft > KWSYS_ST_BUFFER)? KWSYS_ST_BUFFER : static_cast<kwsys_ios::streamsize>(nleft);
1764 finSource.read(source_buf, nnext);
1765 finDestination.read(dest_buf, nnext);
1767 // If either failed to read assume they are different.
1768 if(static_cast<kwsys_ios::streamsize>(finSource.gcount()) != nnext ||
1769 static_cast<kwsys_ios::streamsize>(finDestination.gcount()) != nnext)
1771 return true;
1774 // If this block differs the file differs.
1775 if(memcmp(static_cast<const void*>(source_buf),
1776 static_cast<const void*>(dest_buf),
1777 static_cast<size_t>(nnext)) != 0)
1779 return true;
1782 // Update the byte count remaining.
1783 nleft -= nnext;
1786 // No differences found.
1787 return false;
1791 //----------------------------------------------------------------------------
1793 * Copy a file named by "source" to the file named by "destination".
1795 bool SystemTools::CopyFileAlways(const char* source, const char* destination,
1796 bool copyPermissions)
1798 // If files are the same do not copy
1799 if ( SystemTools::SameFile(source, destination) )
1801 return true;
1803 mode_t perm = 0;
1804 bool perms = SystemTools::GetPermissions(source, perm);
1806 const int bufferSize = 4096;
1807 char buffer[bufferSize];
1809 // If destination is a directory, try to create a file with the same
1810 // name as the source in that directory.
1812 kwsys_stl::string new_destination;
1813 if(SystemTools::FileExists(destination) &&
1814 SystemTools::FileIsDirectory(destination))
1816 new_destination = destination;
1817 SystemTools::ConvertToUnixSlashes(new_destination);
1818 new_destination += '/';
1819 kwsys_stl::string source_name = source;
1820 new_destination += SystemTools::GetFilenameName(source_name);
1821 destination = new_destination.c_str();
1824 // Create destination directory
1826 kwsys_stl::string destination_dir = destination;
1827 destination_dir = SystemTools::GetFilenamePath(destination_dir);
1828 SystemTools::MakeDirectory(destination_dir.c_str());
1830 // Open files
1832 #if defined(_WIN32) || defined(__CYGWIN__)
1833 kwsys_ios::ifstream fin(source,
1834 kwsys_ios::ios::binary | kwsys_ios::ios::in);
1835 #else
1836 kwsys_ios::ifstream fin(source);
1837 #endif
1838 if(!fin)
1840 return false;
1843 // try and remove the destination file so that read only destination files
1844 // can be written to.
1845 // If the remove fails continue so that files in read only directories
1846 // that do not allow file removal can be modified.
1847 SystemTools::RemoveFile(destination);
1849 #if defined(_WIN32) || defined(__CYGWIN__)
1850 kwsys_ios::ofstream fout(destination,
1851 kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1852 #else
1853 kwsys_ios::ofstream fout(destination,
1854 kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1855 #endif
1856 if(!fout)
1858 return false;
1861 // This copy loop is very sensitive on certain platforms with
1862 // slightly broken stream libraries (like HPUX). Normally, it is
1863 // incorrect to not check the error condition on the fin.read()
1864 // before using the data, but the fin.gcount() will be zero if an
1865 // error occurred. Therefore, the loop should be safe everywhere.
1866 while(fin)
1868 fin.read(buffer, bufferSize);
1869 if(fin.gcount())
1871 fout.write(buffer, fin.gcount());
1875 // Make sure the operating system has finished writing the file
1876 // before closing it. This will ensure the file is finished before
1877 // the check below.
1878 fout.flush();
1880 fin.close();
1881 fout.close();
1883 // More checks.
1884 struct stat statSource, statDestination;
1885 statSource.st_size = 12345;
1886 statDestination.st_size = 12345;
1887 if(stat(source, &statSource) != 0)
1889 return false;
1891 else if(stat(destination, &statDestination) != 0)
1893 return false;
1895 else if(statSource.st_size != statDestination.st_size)
1897 return false;
1899 if ( copyPermissions && perms )
1901 if ( !SystemTools::SetPermissions(destination, perm) )
1903 return false;
1906 return true;
1909 //----------------------------------------------------------------------------
1910 bool SystemTools::CopyAFile(const char* source, const char* destination,
1911 bool always, bool copyPermissions)
1913 if(always)
1915 return SystemTools::CopyFileAlways(source, destination, copyPermissions);
1917 else
1919 return SystemTools::CopyFileIfDifferent(source, destination, copyPermissions);
1924 * Copy a directory content from "source" directory to the directory named by
1925 * "destination".
1927 bool SystemTools::CopyADirectory(const char* source, const char* destination,
1928 bool always, bool copyPermissions)
1930 Directory dir;
1931 dir.Load(source);
1932 size_t fileNum;
1933 if ( !SystemTools::MakeDirectory(destination) )
1935 return false;
1937 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
1939 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
1940 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
1942 kwsys_stl::string fullPath = source;
1943 fullPath += "/";
1944 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1945 if(SystemTools::FileIsDirectory(fullPath.c_str()))
1947 kwsys_stl::string fullDestPath = destination;
1948 fullDestPath += "/";
1949 fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1950 if (!SystemTools::CopyADirectory(fullPath.c_str(),
1951 fullDestPath.c_str(),
1952 always,
1953 copyPermissions))
1955 return false;
1958 else
1960 if(!SystemTools::CopyAFile(fullPath.c_str(), destination, always,
1961 copyPermissions))
1963 return false;
1969 return true;
1973 // return size of file; also returns zero if no file exists
1974 unsigned long SystemTools::FileLength(const char* filename)
1976 struct stat fs;
1977 if (stat(filename, &fs) != 0)
1979 return 0;
1981 else
1983 return static_cast<unsigned long>(fs.st_size);
1987 int SystemTools::Strucmp(const char *s1, const char *s2)
1989 // lifted from Graphvis http://www.graphviz.org
1990 while ((*s1 != '\0')
1991 && (tolower(*s1) == tolower(*s2)))
1993 s1++;
1994 s2++;
1997 return tolower(*s1) - tolower(*s2);
2000 // return file's modified time
2001 long int SystemTools::ModifiedTime(const char* filename)
2003 struct stat fs;
2004 if (stat(filename, &fs) != 0)
2006 return 0;
2008 else
2010 return static_cast<long int>(fs.st_mtime);
2014 // return file's creation time
2015 long int SystemTools::CreationTime(const char* filename)
2017 struct stat fs;
2018 if (stat(filename, &fs) != 0)
2020 return 0;
2022 else
2024 return fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0;
2028 bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt)
2030 if (!str || !tmt || strlen(str) > 11)
2032 return false;
2035 struct tm tmt2;
2037 // __DATE__
2038 // The compilation date of the current source file. The date is a string
2039 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
2040 // dates generated by the library function asctime declared in TIME.H.
2042 // index: 012345678901
2043 // format: Mmm dd yyyy
2044 // example: Dec 19 2003
2046 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
2048 char buffer[12];
2049 strcpy(buffer, str);
2051 buffer[3] = 0;
2052 char *ptr = strstr(month_names, buffer);
2053 if (!ptr)
2055 return false;
2058 int month = static_cast<int>((ptr - month_names) / 3);
2059 int day = atoi(buffer + 4);
2060 int year = atoi(buffer + 7);
2062 tmt2.tm_isdst = -1;
2063 tmt2.tm_hour = 0;
2064 tmt2.tm_min = 0;
2065 tmt2.tm_sec = 0;
2066 tmt2.tm_wday = 0;
2067 tmt2.tm_yday = 0;
2068 tmt2.tm_mday = day;
2069 tmt2.tm_mon = month;
2070 tmt2.tm_year = year - 1900;
2072 *tmt = mktime(&tmt2);
2073 return true;
2076 bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt)
2078 if (!str || !tmt || strlen(str) > 26)
2080 return false;
2083 struct tm tmt2;
2085 // __TIMESTAMP__
2086 // The date and time of the last modification of the current source file,
2087 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
2088 /// where Ddd is the abbreviated day of the week and Date is an integer
2089 // from 1 to 31.
2091 // index: 0123456789
2092 // 0123456789
2093 // 0123456789
2094 // format: Ddd Mmm Date hh:mm:ss yyyy
2095 // example: Fri Dec 19 14:34:58 2003
2097 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
2099 char buffer[27];
2100 strcpy(buffer, str);
2102 buffer[7] = 0;
2103 char *ptr = strstr(month_names, buffer + 4);
2104 if (!ptr)
2106 return false;
2109 int month = static_cast<int>((ptr - month_names) / 3);
2110 int day = atoi(buffer + 8);
2111 int hour = atoi(buffer + 11);
2112 int min = atoi(buffer + 14);
2113 int sec = atoi(buffer + 17);
2114 int year = atoi(buffer + 20);
2116 tmt2.tm_isdst = -1;
2117 tmt2.tm_hour = hour;
2118 tmt2.tm_min = min;
2119 tmt2.tm_sec = sec;
2120 tmt2.tm_wday = 0;
2121 tmt2.tm_yday = 0;
2122 tmt2.tm_mday = day;
2123 tmt2.tm_mon = month;
2124 tmt2.tm_year = year - 1900;
2126 *tmt = mktime(&tmt2);
2127 return true;
2130 kwsys_stl::string SystemTools::GetLastSystemError()
2132 int e = errno;
2133 return strerror(e);
2136 bool SystemTools::RemoveFile(const char* source)
2138 #ifdef _WIN32
2139 mode_t mode;
2140 if ( !SystemTools::GetPermissions(source, mode) )
2142 return false;
2144 /* Win32 unlink is stupid --- it fails if the file is read-only */
2145 SystemTools::SetPermissions(source, S_IWRITE);
2146 #endif
2147 bool res = unlink(source) != 0 ? false : true;
2148 #ifdef _WIN32
2149 if ( !res )
2151 SystemTools::SetPermissions(source, mode);
2153 #endif
2154 return res;
2157 bool SystemTools::RemoveADirectory(const char* source)
2159 // Add write permission to the directory so we can modify its
2160 // content to remove files and directories from it.
2161 mode_t mode;
2162 if(SystemTools::GetPermissions(source, mode))
2164 #if defined(_WIN32) && !defined(__CYGWIN__)
2165 mode |= S_IWRITE;
2166 #else
2167 mode |= S_IWUSR;
2168 #endif
2169 SystemTools::SetPermissions(source, mode);
2172 Directory dir;
2173 dir.Load(source);
2174 size_t fileNum;
2175 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
2177 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
2178 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
2180 kwsys_stl::string fullPath = source;
2181 fullPath += "/";
2182 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
2183 if(SystemTools::FileIsDirectory(fullPath.c_str()) &&
2184 !SystemTools::FileIsSymlink(fullPath.c_str()))
2186 if (!SystemTools::RemoveADirectory(fullPath.c_str()))
2188 return false;
2191 else
2193 if(!SystemTools::RemoveFile(fullPath.c_str()))
2195 return false;
2201 return (Rmdir(source) == 0);
2206 size_t SystemTools::GetMaximumFilePathLength()
2208 return KWSYS_SYSTEMTOOLS_MAXPATH;
2212 * Find the file the given name. Searches the given path and then
2213 * the system search path. Returns the full path to the file if it is
2214 * found. Otherwise, the empty string is returned.
2216 kwsys_stl::string SystemTools
2217 ::FindName(const char* name,
2218 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2219 bool no_system_path)
2221 // Add the system search path to our path first
2222 kwsys_stl::vector<kwsys_stl::string> path;
2223 if (!no_system_path)
2225 SystemTools::GetPath(path, "CMAKE_FILE_PATH");
2226 SystemTools::GetPath(path);
2228 // now add the additional paths
2230 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
2231 i != userPaths.end(); ++i)
2233 path.push_back(*i);
2236 // Add a trailing slash to all paths to aid the search process.
2238 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2239 i != path.end(); ++i)
2241 kwsys_stl::string& p = *i;
2242 if(p.empty() || p[p.size()-1] != '/')
2244 p += "/";
2248 // now look for the file
2249 kwsys_stl::string tryPath;
2250 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
2251 p != path.end(); ++p)
2253 tryPath = *p;
2254 tryPath += name;
2255 if(SystemTools::FileExists(tryPath.c_str()))
2257 return tryPath;
2260 // Couldn't find the file.
2261 return "";
2265 * Find the file the given name. Searches the given path and then
2266 * the system search path. Returns the full path to the file if it is
2267 * found. Otherwise, the empty string is returned.
2269 kwsys_stl::string SystemTools
2270 ::FindFile(const char* name,
2271 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2272 bool no_system_path)
2274 kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
2275 if(tryPath != "" && !SystemTools::FileIsDirectory(tryPath.c_str()))
2277 return SystemTools::CollapseFullPath(tryPath.c_str());
2279 // Couldn't find the file.
2280 return "";
2284 * Find the directory the given name. Searches the given path and then
2285 * the system search path. Returns the full path to the directory if it is
2286 * found. Otherwise, the empty string is returned.
2288 kwsys_stl::string SystemTools
2289 ::FindDirectory(const char* name,
2290 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2291 bool no_system_path)
2293 kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
2294 if(tryPath != "" && SystemTools::FileIsDirectory(tryPath.c_str()))
2296 return SystemTools::CollapseFullPath(tryPath.c_str());
2298 // Couldn't find the file.
2299 return "";
2303 * Find the executable with the given name. Searches the given path and then
2304 * the system search path. Returns the full path to the executable if it is
2305 * found. Otherwise, the empty string is returned.
2307 kwsys_stl::string SystemTools::FindProgram(
2308 const char* nameIn,
2309 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
2310 bool no_system_path)
2312 if(!nameIn || !*nameIn)
2314 return "";
2316 kwsys_stl::string name = nameIn;
2317 kwsys_stl::vector<kwsys_stl::string> extensions;
2318 #if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
2319 bool hasExtension = false;
2320 // check to see if the name already has a .xxx at
2321 // the end of it
2322 if(name.size() > 3 && name[name.size()-4] == '.')
2324 hasExtension = true;
2326 // on windows try .com then .exe
2327 if(!hasExtension)
2329 extensions.push_back(".com");
2330 extensions.push_back(".exe");
2332 #endif
2333 kwsys_stl::string tryPath;
2335 // first try with extensions if the os supports them
2336 if(extensions.size())
2338 for(kwsys_stl::vector<kwsys_stl::string>::iterator i =
2339 extensions.begin(); i != extensions.end(); ++i)
2341 tryPath = name;
2342 tryPath += *i;
2343 if(SystemTools::FileExists(tryPath.c_str()) &&
2344 !SystemTools::FileIsDirectory(tryPath.c_str()))
2346 return SystemTools::CollapseFullPath(tryPath.c_str());
2350 // now try just the name
2351 tryPath = name;
2352 if(SystemTools::FileExists(tryPath.c_str()) &&
2353 !SystemTools::FileIsDirectory(tryPath.c_str()))
2355 return SystemTools::CollapseFullPath(tryPath.c_str());
2357 // now construct the path
2358 kwsys_stl::vector<kwsys_stl::string> path;
2359 // Add the system search path to our path.
2360 if (!no_system_path)
2362 SystemTools::GetPath(path);
2364 // now add the additional paths
2366 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i =
2367 userPaths.begin(); i != userPaths.end(); ++i)
2369 path.push_back(*i);
2372 // Add a trailing slash to all paths to aid the search process.
2374 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2375 i != path.end(); ++i)
2377 kwsys_stl::string& p = *i;
2378 if(p.empty() || p[p.size()-1] != '/')
2380 p += "/";
2384 // Try each path
2385 for(kwsys_stl::vector<kwsys_stl::string>::iterator p = path.begin();
2386 p != path.end(); ++p)
2388 #ifdef _WIN32
2389 // Remove double quotes from the path on windows
2390 SystemTools::ReplaceString(*p, "\"", "");
2391 #endif
2392 // first try with extensions
2393 if(extensions.size())
2395 for(kwsys_stl::vector<kwsys_stl::string>::iterator ext
2396 = extensions.begin(); ext != extensions.end(); ++ext)
2398 tryPath = *p;
2399 tryPath += name;
2400 tryPath += *ext;
2401 if(SystemTools::FileExists(tryPath.c_str()) &&
2402 !SystemTools::FileIsDirectory(tryPath.c_str()))
2404 return SystemTools::CollapseFullPath(tryPath.c_str());
2408 // now try it without them
2409 tryPath = *p;
2410 tryPath += name;
2411 if(SystemTools::FileExists(tryPath.c_str()) &&
2412 !SystemTools::FileIsDirectory(tryPath.c_str()))
2414 return SystemTools::CollapseFullPath(tryPath.c_str());
2417 // Couldn't find the program.
2418 return "";
2421 kwsys_stl::string SystemTools::FindProgram(
2422 const kwsys_stl::vector<kwsys_stl::string>& names,
2423 const kwsys_stl::vector<kwsys_stl::string>& path,
2424 bool noSystemPath)
2426 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator it = names.begin();
2427 it != names.end() ; ++it)
2429 // Try to find the program.
2430 kwsys_stl::string result = SystemTools::FindProgram(it->c_str(),
2431 path,
2432 noSystemPath);
2433 if ( !result.empty() )
2435 return result;
2438 return "";
2442 * Find the library with the given name. Searches the given path and then
2443 * the system search path. Returns the full path to the library if it is
2444 * found. Otherwise, the empty string is returned.
2446 kwsys_stl::string SystemTools
2447 ::FindLibrary(const char* name,
2448 const kwsys_stl::vector<kwsys_stl::string>& userPaths)
2450 // See if the executable exists as written.
2451 if(SystemTools::FileExists(name) &&
2452 !SystemTools::FileIsDirectory(name))
2454 return SystemTools::CollapseFullPath(name);
2457 // Add the system search path to our path.
2458 kwsys_stl::vector<kwsys_stl::string> path;
2459 SystemTools::GetPath(path);
2460 // now add the additional paths
2462 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
2463 i != userPaths.end(); ++i)
2465 path.push_back(*i);
2468 // Add a trailing slash to all paths to aid the search process.
2470 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
2471 i != path.end(); ++i)
2473 kwsys_stl::string& p = *i;
2474 if(p.empty() || p[p.size()-1] != '/')
2476 p += "/";
2480 kwsys_stl::string tryPath;
2481 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
2482 p != path.end(); ++p)
2484 #if defined(__APPLE__)
2485 tryPath = *p;
2486 tryPath += name;
2487 tryPath += ".framework";
2488 if(SystemTools::FileExists(tryPath.c_str())
2489 && SystemTools::FileIsDirectory(tryPath.c_str()))
2491 return SystemTools::CollapseFullPath(tryPath.c_str());
2493 #endif
2494 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
2495 tryPath = *p;
2496 tryPath += name;
2497 tryPath += ".lib";
2498 if(SystemTools::FileExists(tryPath.c_str())
2499 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2501 return SystemTools::CollapseFullPath(tryPath.c_str());
2503 #else
2504 tryPath = *p;
2505 tryPath += "lib";
2506 tryPath += name;
2507 tryPath += ".so";
2508 if(SystemTools::FileExists(tryPath.c_str())
2509 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2511 return SystemTools::CollapseFullPath(tryPath.c_str());
2513 tryPath = *p;
2514 tryPath += "lib";
2515 tryPath += name;
2516 tryPath += ".a";
2517 if(SystemTools::FileExists(tryPath.c_str())
2518 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2520 return SystemTools::CollapseFullPath(tryPath.c_str());
2522 tryPath = *p;
2523 tryPath += "lib";
2524 tryPath += name;
2525 tryPath += ".sl";
2526 if(SystemTools::FileExists(tryPath.c_str())
2527 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2529 return SystemTools::CollapseFullPath(tryPath.c_str());
2531 tryPath = *p;
2532 tryPath += "lib";
2533 tryPath += name;
2534 tryPath += ".dylib";
2535 if(SystemTools::FileExists(tryPath.c_str())
2536 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2538 return SystemTools::CollapseFullPath(tryPath.c_str());
2540 tryPath = *p;
2541 tryPath += "lib";
2542 tryPath += name;
2543 tryPath += ".dll";
2544 if(SystemTools::FileExists(tryPath.c_str())
2545 && !SystemTools::FileIsDirectory(tryPath.c_str()))
2547 return SystemTools::CollapseFullPath(tryPath.c_str());
2549 #endif
2552 // Couldn't find the library.
2553 return "";
2556 kwsys_stl::string SystemTools::GetRealPath(const char* path)
2558 kwsys_stl::string ret;
2559 Realpath(path, ret);
2560 return ret;
2563 bool SystemTools::FileIsDirectory(const char* name)
2565 // Remove any trailing slash from the name.
2566 char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
2567 size_t last = strlen(name)-1;
2568 if(last > 0 && (name[last] == '/' || name[last] == '\\')
2569 && strcmp(name, "/") !=0)
2571 memcpy(buffer, name, last);
2572 buffer[last] = 0;
2573 name = buffer;
2576 // Now check the file node type.
2577 struct stat fs;
2578 if(stat(name, &fs) == 0)
2580 #if defined( _WIN32 )
2581 return ((fs.st_mode & _S_IFDIR) != 0);
2582 #else
2583 return S_ISDIR(fs.st_mode);
2584 #endif
2586 else
2588 return false;
2592 bool SystemTools::FileIsSymlink(const char* name)
2594 #if defined( _WIN32 )
2595 (void)name;
2596 return false;
2597 #else
2598 struct stat fs;
2599 if(lstat(name, &fs) == 0)
2601 return S_ISLNK(fs.st_mode);
2603 else
2605 return false;
2607 #endif
2610 #if defined(_WIN32) && !defined(__CYGWIN__)
2611 bool SystemTools::CreateSymlink(const char*, const char*)
2613 return false;
2615 #else
2616 bool SystemTools::CreateSymlink(const char* origName, const char* newName)
2618 return symlink(origName, newName) >= 0;
2620 #endif
2622 #if defined(_WIN32) && !defined(__CYGWIN__)
2623 bool SystemTools::ReadSymlink(const char*, kwsys_stl::string&)
2625 return false;
2627 #else
2628 bool SystemTools::ReadSymlink(const char* newName,
2629 kwsys_stl::string& origName)
2631 char buf[KWSYS_SYSTEMTOOLS_MAXPATH+1];
2632 int count =
2633 static_cast<int>(readlink(newName, buf, KWSYS_SYSTEMTOOLS_MAXPATH));
2634 if(count >= 0)
2636 // Add null-terminator.
2637 buf[count] = 0;
2638 origName = buf;
2639 return true;
2641 else
2643 return false;
2646 #endif
2648 int SystemTools::ChangeDirectory(const char *dir)
2650 return Chdir(dir);
2653 kwsys_stl::string SystemTools::GetCurrentWorkingDirectory(bool collapse)
2655 char buf[2048];
2656 const char* cwd = Getcwd(buf, 2048);
2657 kwsys_stl::string path;
2658 if ( cwd )
2660 path = cwd;
2662 if(collapse)
2664 return SystemTools::CollapseFullPath(path.c_str());
2666 return path;
2669 kwsys_stl::string SystemTools::GetProgramPath(const char* in_name)
2671 kwsys_stl::string dir, file;
2672 SystemTools::SplitProgramPath(in_name, dir, file);
2673 return dir;
2676 bool SystemTools::SplitProgramPath(const char* in_name,
2677 kwsys_stl::string& dir,
2678 kwsys_stl::string& file,
2679 bool)
2681 dir = in_name;
2682 file = "";
2683 SystemTools::ConvertToUnixSlashes(dir);
2685 if(!SystemTools::FileIsDirectory(dir.c_str()))
2687 kwsys_stl::string::size_type slashPos = dir.rfind("/");
2688 if(slashPos != kwsys_stl::string::npos)
2690 file = dir.substr(slashPos+1);
2691 dir = dir.substr(0, slashPos);
2693 else
2695 file = dir;
2696 dir = "";
2699 if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str()))
2701 kwsys_stl::string oldDir = in_name;
2702 SystemTools::ConvertToUnixSlashes(oldDir);
2703 dir = in_name;
2704 return false;
2706 return true;
2709 bool SystemTools::FindProgramPath(const char* argv0,
2710 kwsys_stl::string& pathOut,
2711 kwsys_stl::string& errorMsg,
2712 const char* exeName,
2713 const char* buildDir,
2714 const char* installPrefix )
2716 kwsys_stl::vector<kwsys_stl::string> failures;
2717 kwsys_stl::string self = argv0 ? argv0 : "";
2718 failures.push_back(self);
2719 SystemTools::ConvertToUnixSlashes(self);
2720 self = SystemTools::FindProgram(self.c_str());
2721 if(!SystemTools::FileExists(self.c_str()))
2723 if(buildDir)
2725 kwsys_stl::string intdir = ".";
2726 #ifdef CMAKE_INTDIR
2727 intdir = CMAKE_INTDIR;
2728 #endif
2729 self = buildDir;
2730 self += "/bin/";
2731 self += intdir;
2732 self += "/";
2733 self += exeName;
2734 self += SystemTools::GetExecutableExtension();
2737 if(installPrefix)
2739 if(!SystemTools::FileExists(self.c_str()))
2741 failures.push_back(self);
2742 self = installPrefix;
2743 self += "/bin/";
2744 self += exeName;
2747 if(!SystemTools::FileExists(self.c_str()))
2749 failures.push_back(self);
2750 kwsys_ios::ostringstream msg;
2751 msg << "Can not find the command line program ";
2752 if (exeName)
2754 msg << exeName;
2756 msg << "\n";
2757 if (argv0)
2759 msg << " argv[0] = \"" << argv0 << "\"\n";
2761 msg << " Attempted paths:\n";
2762 kwsys_stl::vector<kwsys_stl::string>::iterator i;
2763 for(i=failures.begin(); i != failures.end(); ++i)
2765 msg << " \"" << i->c_str() << "\"\n";
2767 errorMsg = msg.str();
2768 return false;
2770 pathOut = self;
2771 return true;
2775 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative)
2777 return SystemTools::CollapseFullPath(in_relative, 0);
2780 void SystemTools::AddTranslationPath(const char * a, const char * b)
2782 kwsys_stl::string path_a = a;
2783 kwsys_stl::string path_b = b;
2784 SystemTools::ConvertToUnixSlashes(path_a);
2785 SystemTools::ConvertToUnixSlashes(path_b);
2786 // First check this is a directory path, since we don't want the table to
2787 // grow too fat
2788 if( SystemTools::FileIsDirectory( path_a.c_str() ) )
2790 // Make sure the path is a full path and does not contain no '..'
2791 // Ken--the following code is incorrect. .. can be in a valid path
2792 // for example /home/martink/MyHubba...Hubba/Src
2793 if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..")
2794 == kwsys_stl::string::npos )
2796 // Before inserting make sure path ends with '/'
2797 if(path_a.size() && path_a[path_a.size() -1] != '/')
2799 path_a += '/';
2801 if(path_b.size() && path_b[path_b.size() -1] != '/')
2803 path_b += '/';
2805 if( !(path_a == path_b) )
2807 SystemTools::TranslationMap->insert(
2808 SystemToolsTranslationMap::value_type(path_a, path_b));
2814 void SystemTools::AddKeepPath(const char* dir)
2816 kwsys_stl::string cdir;
2817 Realpath(SystemTools::CollapseFullPath(dir).c_str(), cdir);
2818 SystemTools::AddTranslationPath(cdir.c_str(), dir);
2821 void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
2823 // Do not translate paths that are too short to have meaningful
2824 // translations.
2825 if(path.size() < 2)
2827 return;
2830 // Always add a trailing slash before translation. It does not
2831 // matter if this adds an extra slash, but we do not want to
2832 // translate part of a directory (like the foo part of foo-dir).
2833 path += "/";
2835 // In case a file was specified we still have to go through this:
2836 // Now convert any path found in the table back to the one desired:
2837 kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>::const_iterator it;
2838 for(it = SystemTools::TranslationMap->begin();
2839 it != SystemTools::TranslationMap->end();
2840 ++it )
2842 // We need to check of the path is a substring of the other path
2843 if(path.find( it->first ) == 0)
2845 path = path.replace( 0, it->first.size(), it->second);
2849 // Remove the trailing slash we added before.
2850 path.erase(path.end()-1, path.end());
2853 void
2854 SystemToolsAppendComponents(
2855 kwsys_stl::vector<kwsys_stl::string>& out_components,
2856 kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
2857 kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
2859 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = first;
2860 i != last; ++i)
2862 if(*i == "..")
2864 if(out_components.begin() != out_components.end())
2866 out_components.erase(out_components.end()-1, out_components.end());
2869 else if(!(*i == ".") && !(*i == ""))
2871 out_components.push_back(*i);
2876 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
2877 const char* in_base)
2879 // Collect the output path components.
2880 kwsys_stl::vector<kwsys_stl::string> out_components;
2882 // Split the input path components.
2883 kwsys_stl::vector<kwsys_stl::string> path_components;
2884 SystemTools::SplitPath(in_path, path_components);
2886 // If the input path is relative, start with a base path.
2887 if(path_components[0].length() == 0)
2889 kwsys_stl::vector<kwsys_stl::string> base_components;
2890 if(in_base)
2892 // Use the given base path.
2893 SystemTools::SplitPath(in_base, base_components);
2895 else
2897 // Use the current working directory as a base path.
2898 char buf[2048];
2899 if(const char* cwd = Getcwd(buf, 2048))
2901 SystemTools::SplitPath(cwd, base_components);
2903 else
2905 // ??
2909 // Append base path components to the output path.
2910 out_components.push_back(base_components[0]);
2911 SystemToolsAppendComponents(out_components,
2912 base_components.begin()+1,
2913 base_components.end());
2916 // Append input path components to the output path.
2917 SystemToolsAppendComponents(out_components,
2918 path_components.begin(),
2919 path_components.end());
2921 // Transform the path back to a string.
2922 kwsys_stl::string newPath = SystemTools::JoinPath(out_components);
2924 // Update the translation table with this potentially new path. I am not
2925 // sure why this line is here, it seems really questionable, but yet I
2926 // would put good money that if I remove it something will break, basically
2927 // from what I can see it created a mapping from the collapsed path, to be
2928 // replaced by the input path, which almost completely does the opposite of
2929 // this function, the only thing preventing this from happening a lot is
2930 // that if the in_path has a .. in it, then it is not added to the
2931 // translation table. So for most calls this either does nothing due to the
2932 // .. or it adds a translation between identical paths as nothing was
2933 // collapsed, so I am going to try to comment it out, and see what hits the
2934 // fan, hopefully quickly.
2935 // Commented out line below:
2936 //SystemTools::AddTranslationPath(newPath.c_str(), in_path);
2938 SystemTools::CheckTranslationPath(newPath);
2939 #ifdef _WIN32
2940 newPath = SystemTools::GetActualCaseForPath(newPath.c_str());
2941 SystemTools::ConvertToUnixSlashes(newPath);
2942 #endif
2943 // Return the reconstructed path.
2944 return newPath;
2947 // compute the relative path from here to there
2948 kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remote)
2950 if(!SystemTools::FileIsFullPath(local))
2952 return "";
2954 if(!SystemTools::FileIsFullPath(remote))
2956 return "";
2959 // split up both paths into arrays of strings using / as a separator
2960 kwsys_stl::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true);
2961 kwsys_stl::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true);
2962 kwsys_stl::vector<kwsys::String> commonPath; // store shared parts of path in this array
2963 kwsys_stl::vector<kwsys::String> finalPath; // store the final relative path here
2964 // count up how many matching directory names there are from the start
2965 unsigned int sameCount = 0;
2966 while(
2967 ((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1)))
2969 // for windows and apple do a case insensitive string compare
2970 #if defined(_WIN32) || defined(__APPLE__)
2971 SystemTools::Strucmp(localSplit[sameCount].c_str(),
2972 remoteSplit[sameCount].c_str()) == 0
2973 #else
2974 localSplit[sameCount] == remoteSplit[sameCount]
2975 #endif
2978 // put the common parts of the path into the commonPath array
2979 commonPath.push_back(localSplit[sameCount]);
2980 // erase the common parts of the path from the original path arrays
2981 localSplit[sameCount] = "";
2982 remoteSplit[sameCount] = "";
2983 sameCount++;
2986 // If there is nothing in common at all then just return the full
2987 // path. This is the case only on windows when the paths have
2988 // different drive letters. On unix two full paths always at least
2989 // have the root "/" in common so we will return a relative path
2990 // that passes through the root directory.
2991 if(sameCount == 0)
2993 return remote;
2996 // for each entry that is not common in the local path
2997 // add a ../ to the finalpath array, this gets us out of the local
2998 // path into the remote dir
2999 for(unsigned int i = 0; i < localSplit.size(); ++i)
3001 if(localSplit[i].size())
3003 finalPath.push_back("../");
3006 // for each entry that is not common in the remote path add it
3007 // to the final path.
3008 for(kwsys_stl::vector<String>::iterator vit = remoteSplit.begin();
3009 vit != remoteSplit.end(); ++vit)
3011 if(vit->size())
3013 finalPath.push_back(*vit);
3016 kwsys_stl::string relativePath; // result string
3017 // now turn the array of directories into a unix path by puttint /
3018 // between each entry that does not already have one
3019 for(kwsys_stl::vector<String>::iterator vit1 = finalPath.begin();
3020 vit1 != finalPath.end(); ++vit1)
3022 if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
3024 relativePath += "/";
3026 relativePath += *vit1;
3028 return relativePath;
3031 // OK, some fun stuff to get the actual case of a given path.
3032 // Basically, you just need to call ShortPath, then GetLongPathName,
3033 // However, GetLongPathName is not implemented on windows NT and 95,
3034 // so we have to simulate it on those versions
3035 #ifdef _WIN32
3036 int OldWindowsGetLongPath(kwsys_stl::string const& shortPath,
3037 kwsys_stl::string& longPath )
3039 kwsys_stl::string::size_type iFound = shortPath.rfind('/');
3040 if (iFound > 1 && iFound != shortPath.npos)
3042 // recurse to peel off components
3044 if (OldWindowsGetLongPath(shortPath.substr(0, iFound), longPath) > 0)
3046 longPath += '/';
3047 if (shortPath[1] != '/')
3049 WIN32_FIND_DATA findData;
3051 // append the long component name to the path
3053 if (INVALID_HANDLE_VALUE != ::FindFirstFile
3054 (shortPath.c_str(), &findData))
3056 longPath += findData.cFileName;
3058 else
3060 // if FindFirstFile fails, return the error code
3062 longPath = "";
3063 return 0;
3068 else
3070 longPath = shortPath;
3072 return (int)longPath.size();
3076 int PortableGetLongPathName(const char* pathIn,
3077 kwsys_stl::string & longPath)
3079 HMODULE lh = LoadLibrary("Kernel32.dll");
3080 if(lh)
3082 FARPROC proc = GetProcAddress(lh, "GetLongPathNameA");
3083 if(proc)
3085 typedef DWORD (WINAPI * GetLongFunctionPtr) (LPCSTR,LPSTR,DWORD);
3086 GetLongFunctionPtr func = (GetLongFunctionPtr)proc;
3087 char buffer[MAX_PATH+1];
3088 int len = (*func)(pathIn, buffer, MAX_PATH+1);
3089 if(len == 0 || len > MAX_PATH+1)
3091 FreeLibrary(lh);
3092 return 0;
3094 longPath = buffer;
3095 FreeLibrary(lh);
3096 return len;
3098 FreeLibrary(lh);
3100 return OldWindowsGetLongPath(pathIn, longPath);
3102 #endif
3105 //----------------------------------------------------------------------------
3106 kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p)
3108 #ifndef _WIN32
3109 return p;
3110 #else
3111 // Check to see if actual case has already been called
3112 // for this path, and the result is stored in the LongPathMap
3113 SystemToolsTranslationMap::iterator i =
3114 SystemTools::LongPathMap->find(p);
3115 if(i != SystemTools::LongPathMap->end())
3117 return i->second;
3119 kwsys_stl::string shortPath;
3120 if(!SystemTools::GetShortPath(p, shortPath))
3122 return p;
3124 kwsys_stl::string longPath;
3125 int len = PortableGetLongPathName(shortPath.c_str(), longPath);
3126 if(len == 0 || len > MAX_PATH+1)
3128 return p;
3130 // Use original path if conversion back to a long path failed.
3131 if(longPath == shortPath)
3133 longPath = p;
3135 // make sure drive letter is always upper case
3136 if(longPath.size() > 1 && longPath[1] == ':')
3138 longPath[0] = toupper(longPath[0]);
3140 (*SystemTools::LongPathMap)[p] = longPath;
3141 return longPath;
3142 #endif
3145 //----------------------------------------------------------------------------
3146 const char* SystemTools::SplitPathRootComponent(const char* p,
3147 kwsys_stl::string* root)
3149 // Identify the root component.
3150 const char* c = p;
3151 if((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\'))
3153 // Network path.
3154 if(root)
3156 *root = "//";
3158 c += 2;
3160 else if(c[0] == '/')
3162 // Unix path.
3163 if(root)
3165 *root = "/";
3167 c += 1;
3169 else if(c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\'))
3171 // Windows path.
3172 if(root)
3174 (*root) = "_:/";
3175 (*root)[0] = c[0];
3177 c += 3;
3179 else if(c[0] && c[1] == ':')
3181 // Path relative to a windows drive working directory.
3182 if(root)
3184 (*root) = "_:";
3185 (*root)[0] = c[0];
3187 c += 2;
3189 else if(c[0] == '~')
3191 // Home directory. The returned root should always have a
3192 // trailing slash so that appending components as
3193 // c[0]c[1]/c[2]/... works. The remaining path returned should
3194 // skip the first slash if it exists:
3196 // "~" : root = "~/" , return ""
3197 // "~/ : root = "~/" , return ""
3198 // "~/x : root = "~/" , return "x"
3199 // "~u" : root = "~u/", return ""
3200 // "~u/" : root = "~u/", return ""
3201 // "~u/x" : root = "~u/", return "x"
3202 size_t n = 1;
3203 while(c[n] && c[n] != '/')
3205 ++n;
3207 if(root)
3209 root->assign(c, n);
3210 *root += '/';
3212 if(c[n] == '/')
3214 ++n;
3216 c += n;
3218 else
3220 // Relative path.
3221 if(root)
3223 *root = "";
3227 // Return the remaining path.
3228 return c;
3231 //----------------------------------------------------------------------------
3232 void SystemTools::SplitPath(const char* p,
3233 kwsys_stl::vector<kwsys_stl::string>& components,
3234 bool expand_home_dir)
3236 const char* c = p;
3237 components.clear();
3239 // Identify the root component.
3241 kwsys_stl::string root;
3242 c = SystemTools::SplitPathRootComponent(c, &root);
3244 // Expand home directory references if requested.
3245 if(expand_home_dir && !root.empty() && root[0] == '~')
3247 kwsys_stl::string homedir;
3248 root = root.substr(0, root.size()-1);
3249 if(root.size() == 1)
3251 #if defined(_WIN32) && !defined(__CYGWIN__)
3252 if(const char* userp = getenv("USERPROFILE"))
3254 homedir = userp;
3256 else
3257 #endif
3258 if(const char* h = getenv("HOME"))
3260 homedir = h;
3263 #ifdef HAVE_GETPWNAM
3264 else if(passwd* pw = getpwnam(root.c_str()+1))
3266 if(pw->pw_dir)
3268 homedir = pw->pw_dir;
3271 #endif
3272 if(!homedir.empty() && (homedir[homedir.size()-1] == '/' ||
3273 homedir[homedir.size()-1] == '\\'))
3275 homedir = homedir.substr(0, homedir.size()-1);
3277 SystemTools::SplitPath(homedir.c_str(), components);
3279 else
3281 components.push_back(root);
3285 // Parse the remaining components.
3286 const char* first = c;
3287 const char* last = first;
3288 for(;*last; ++last)
3290 if(*last == '/' || *last == '\\')
3292 // End of a component. Save it.
3293 components.push_back(
3294 kwsys_stl::string(first,static_cast<kwsys_stl::string::size_type>(
3295 last-first)));
3296 first = last+1;
3300 // Save the last component unless there were no components.
3301 if(last != c)
3303 components.push_back(
3304 kwsys_stl::string(first,static_cast<kwsys_stl::string::size_type>(
3305 last-first)));
3309 //----------------------------------------------------------------------------
3310 kwsys_stl::string
3311 SystemTools::JoinPath(const kwsys_stl::vector<kwsys_stl::string>& components)
3313 return SystemTools::JoinPath(components.begin(), components.end());
3316 //----------------------------------------------------------------------------
3317 kwsys_stl::string
3318 SystemTools
3319 ::JoinPath(kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
3320 kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
3322 // Construct result in a single string.
3323 kwsys_stl::string result;
3325 // The first two components do not add a slash.
3326 if(first != last)
3328 result += *first++;
3330 if(first != last)
3332 result += *first++;
3335 // All remaining components are always separated with a slash.
3336 while(first != last)
3338 result += "/";
3339 result += *first++;
3342 // Return the concatenated result.
3343 return result;
3346 //----------------------------------------------------------------------------
3347 bool SystemTools::ComparePath(const char* c1, const char* c2)
3349 #if defined(_WIN32) || defined(__APPLE__)
3350 # ifdef _MSC_VER
3351 return _stricmp(c1, c2) == 0;
3352 # elif defined(__APPLE__) || defined(__GNUC__)
3353 return strcasecmp(c1, c2) == 0;
3354 #else
3355 return SystemTools::Strucmp(c1, c2) == 0;
3356 # endif
3357 #else
3358 return strcmp(c1, c2) == 0;
3359 #endif
3362 //----------------------------------------------------------------------------
3363 bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines, char separator)
3365 kwsys_stl::string data(str);
3366 kwsys_stl::string::size_type lpos = 0;
3367 while(lpos < data.length())
3369 kwsys_stl::string::size_type rpos = data.find_first_of(separator, lpos);
3370 if(rpos == kwsys_stl::string::npos)
3372 // Line ends at end of string without a newline.
3373 lines.push_back(data.substr(lpos));
3374 return false;
3376 else
3378 // Line ends in a "\n", remove the character.
3379 lines.push_back(data.substr(lpos, rpos-lpos));
3381 lpos = rpos+1;
3383 return true;
3386 //----------------------------------------------------------------------------
3387 bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines)
3389 kwsys_stl::string data(str);
3390 kwsys_stl::string::size_type lpos = 0;
3391 while(lpos < data.length())
3393 kwsys_stl::string::size_type rpos = data.find_first_of("\n", lpos);
3394 if(rpos == kwsys_stl::string::npos)
3396 // Line ends at end of string without a newline.
3397 lines.push_back(data.substr(lpos));
3398 return false;
3400 if((rpos > lpos) && (data[rpos-1] == '\r'))
3402 // Line ends in a "\r\n" pair, remove both characters.
3403 lines.push_back(data.substr(lpos, (rpos-1)-lpos));
3405 else
3407 // Line ends in a "\n", remove the character.
3408 lines.push_back(data.substr(lpos, rpos-lpos));
3410 lpos = rpos+1;
3412 return true;
3416 * Return path of a full filename (no trailing slashes).
3417 * Warning: returned path is converted to Unix slashes format.
3419 kwsys_stl::string SystemTools::GetFilenamePath(const kwsys_stl::string& filename)
3421 kwsys_stl::string fn = filename;
3422 SystemTools::ConvertToUnixSlashes(fn);
3424 kwsys_stl::string::size_type slash_pos = fn.rfind("/");
3425 if(slash_pos != kwsys_stl::string::npos)
3427 kwsys_stl::string ret = fn.substr(0, slash_pos);
3428 if(ret.size() == 2 && ret[1] == ':')
3430 return ret + '/';
3432 if(ret.size() == 0)
3434 return "/";
3436 return ret;
3438 else
3440 return "";
3446 * Return file name of a full filename (i.e. file name without path).
3448 kwsys_stl::string SystemTools::GetFilenameName(const kwsys_stl::string& filename)
3450 #if defined(_WIN32)
3451 kwsys_stl::string::size_type slash_pos = filename.find_last_of("/\\");
3452 #else
3453 kwsys_stl::string::size_type slash_pos = filename.find_last_of("/");
3454 #endif
3455 if(slash_pos != kwsys_stl::string::npos)
3457 return filename.substr(slash_pos + 1);
3459 else
3461 return filename;
3467 * Return file extension of a full filename (dot included).
3468 * Warning: this is the longest extension (for example: .tar.gz)
3470 kwsys_stl::string SystemTools::GetFilenameExtension(const kwsys_stl::string& filename)
3472 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3473 kwsys_stl::string::size_type dot_pos = name.find(".");
3474 if(dot_pos != kwsys_stl::string::npos)
3476 return name.substr(dot_pos);
3478 else
3480 return "";
3485 * Return file extension of a full filename (dot included).
3486 * Warning: this is the shortest extension (for example: .gz of .tar.gz)
3488 kwsys_stl::string SystemTools::GetFilenameLastExtension(const kwsys_stl::string& filename)
3490 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3491 kwsys_stl::string::size_type dot_pos = name.rfind(".");
3492 if(dot_pos != kwsys_stl::string::npos)
3494 return name.substr(dot_pos);
3496 else
3498 return "";
3503 * Return file name without extension of a full filename (i.e. without path).
3504 * Warning: it considers the longest extension (for example: .tar.gz)
3506 kwsys_stl::string SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string& filename)
3508 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3509 kwsys_stl::string::size_type dot_pos = name.find(".");
3510 if(dot_pos != kwsys_stl::string::npos)
3512 return name.substr(0, dot_pos);
3514 else
3516 return name;
3522 * Return file name without extension of a full filename (i.e. without path).
3523 * Warning: it considers the last extension (for example: removes .gz
3524 * from .tar.gz)
3526 kwsys_stl::string
3527 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string& filename)
3529 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
3530 kwsys_stl::string::size_type dot_pos = name.rfind(".");
3531 if(dot_pos != kwsys_stl::string::npos)
3533 return name.substr(0, dot_pos);
3535 else
3537 return name;
3541 bool SystemTools::FileHasSignature(const char *filename,
3542 const char *signature,
3543 long offset)
3545 if (!filename || !signature)
3547 return false;
3550 FILE *fp;
3551 fp = fopen(filename, "rb");
3552 if (!fp)
3554 return false;
3557 fseek(fp, offset, SEEK_SET);
3559 bool res = false;
3560 size_t signature_len = strlen(signature);
3561 char *buffer = new char [signature_len];
3563 if (fread(buffer, 1, signature_len, fp) == signature_len)
3565 res = (!strncmp(buffer, signature, signature_len) ? true : false);
3568 delete [] buffer;
3570 fclose(fp);
3571 return res;
3574 SystemTools::FileTypeEnum
3575 SystemTools::DetectFileType(const char *filename,
3576 unsigned long length,
3577 double percent_bin)
3579 if (!filename || percent_bin < 0)
3581 return SystemTools::FileTypeUnknown;
3584 FILE *fp;
3585 fp = fopen(filename, "rb");
3586 if (!fp)
3588 return SystemTools::FileTypeUnknown;
3591 // Allocate buffer and read bytes
3593 unsigned char *buffer = new unsigned char [length];
3594 size_t read_length = fread(buffer, 1, length, fp);
3595 fclose(fp);
3596 if (read_length == 0)
3598 return SystemTools::FileTypeUnknown;
3601 // Loop over contents and count
3603 size_t text_count = 0;
3605 const unsigned char *ptr = buffer;
3606 const unsigned char *buffer_end = buffer + read_length;
3608 while (ptr != buffer_end)
3610 if ((*ptr >= 0x20 && *ptr <= 0x7F) ||
3611 *ptr == '\n' ||
3612 *ptr == '\r' ||
3613 *ptr == '\t')
3615 text_count++;
3617 ptr++;
3620 delete [] buffer;
3622 double current_percent_bin =
3623 (static_cast<double>(read_length - text_count) /
3624 static_cast<double>(read_length));
3626 if (current_percent_bin >= percent_bin)
3628 return SystemTools::FileTypeBinary;
3631 return SystemTools::FileTypeText;
3634 bool SystemTools::LocateFileInDir(const char *filename,
3635 const char *dir,
3636 kwsys_stl::string& filename_found,
3637 int try_filename_dirs)
3639 if (!filename || !dir)
3641 return false;
3644 // Get the basename of 'filename'
3646 kwsys_stl::string filename_base = SystemTools::GetFilenameName(filename);
3648 // Check if 'dir' is really a directory
3649 // If win32 and matches something like C:, accept it as a dir
3651 kwsys_stl::string real_dir;
3652 if (!SystemTools::FileIsDirectory(dir))
3654 #if defined( _WIN32 )
3655 size_t dir_len = strlen(dir);
3656 if (dir_len < 2 || dir[dir_len - 1] != ':')
3658 #endif
3659 real_dir = SystemTools::GetFilenamePath(dir);
3660 dir = real_dir.c_str();
3661 #if defined( _WIN32 )
3663 #endif
3666 // Try to find the file in 'dir'
3668 bool res = false;
3669 if (filename_base.size() && dir)
3671 size_t dir_len = strlen(dir);
3672 int need_slash =
3673 (dir_len && dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\');
3675 kwsys_stl::string temp = dir;
3676 if (need_slash)
3678 temp += "/";
3680 temp += filename_base;
3682 if (SystemTools::FileExists(temp.c_str()))
3684 res = true;
3685 filename_found = temp;
3688 // If not found, we can try harder by appending part of the file to
3689 // to the directory to look inside.
3690 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
3691 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
3693 else if (try_filename_dirs)
3695 kwsys_stl::string filename_dir(filename);
3696 kwsys_stl::string filename_dir_base;
3697 kwsys_stl::string filename_dir_bases;
3700 filename_dir = SystemTools::GetFilenamePath(filename_dir);
3701 filename_dir_base = SystemTools::GetFilenameName(filename_dir);
3702 #if defined( _WIN32 )
3703 if (!filename_dir_base.size() ||
3704 filename_dir_base[filename_dir_base.size() - 1] == ':')
3705 #else
3706 if (!filename_dir_base.size())
3707 #endif
3709 break;
3712 filename_dir_bases = filename_dir_base + "/" + filename_dir_bases;
3714 temp = dir;
3715 if (need_slash)
3717 temp += "/";
3719 temp += filename_dir_bases;
3721 res = SystemTools::LocateFileInDir(
3722 filename_base.c_str(), temp.c_str(), filename_found, 0);
3724 } while (!res && filename_dir_base.size());
3728 return res;
3731 bool SystemTools::FileIsFullPath(const char* in_name)
3733 kwsys_stl::string name = in_name;
3734 #if defined(_WIN32) || defined(__CYGWIN__)
3735 // On Windows, the name must be at least two characters long.
3736 if(name.length() < 2)
3738 return false;
3740 if(name[1] == ':')
3742 return true;
3744 if(name[0] == '\\')
3746 return true;
3748 #else
3749 // On UNIX, the name must be at least one character long.
3750 if(name.length() < 1)
3752 return false;
3754 #endif
3755 #if !defined(_WIN32)
3756 if(name[0] == '~')
3758 return true;
3760 #endif
3761 // On UNIX, the name must begin in a '/'.
3762 // On Windows, if the name begins in a '/', then it is a full
3763 // network path.
3764 if(name[0] == '/')
3766 return true;
3768 return false;
3771 bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
3773 #if defined(WIN32) && !defined(__CYGWIN__)
3774 const int size = int(strlen(path)) +1; // size of return
3775 char *buffer = new char[size]; // create a buffer
3776 char *tempPath = new char[size]; // create a buffer
3777 int ret;
3779 // if the path passed in has quotes around it, first remove the quotes
3780 if (path[0] == '"' && path[strlen(path)-1] == '"')
3782 strcpy(tempPath,path+1);
3783 tempPath[strlen(tempPath)-1] = '\0';
3785 else
3787 strcpy(tempPath,path);
3790 buffer[0] = 0;
3791 ret = GetShortPathName(tempPath, buffer, size);
3793 if(buffer[0] == 0 || ret > size)
3795 delete [] buffer;
3796 delete [] tempPath;
3797 return false;
3799 else
3801 shortPath = buffer;
3802 delete [] buffer;
3803 delete [] tempPath;
3804 return true;
3806 #else
3807 shortPath = path;
3808 return true;
3809 #endif
3812 void SystemTools::SplitProgramFromArgs(const char* path,
3813 kwsys_stl::string& program, kwsys_stl::string& args)
3815 // see if this is a full path to a program
3816 // if so then set program to path and args to nothing
3817 if(SystemTools::FileExists(path))
3819 program = path;
3820 args = "";
3821 return;
3823 // Try to find the program in the path, note the program
3824 // may have spaces in its name so we have to look for it
3825 kwsys_stl::vector<kwsys_stl::string> e;
3826 kwsys_stl::string findProg = SystemTools::FindProgram(path, e);
3827 if(findProg.size())
3829 program = findProg;
3830 args = "";
3831 return;
3834 // Now try and peel off space separated chunks from the end of the string
3835 // so the largest path possible is found allowing for spaces in the path
3836 kwsys_stl::string dir = path;
3837 kwsys_stl::string::size_type spacePos = dir.rfind(' ');
3838 while(spacePos != kwsys_stl::string::npos)
3840 kwsys_stl::string tryProg = dir.substr(0, spacePos);
3841 // See if the file exists
3842 if(SystemTools::FileExists(tryProg.c_str()))
3844 program = tryProg;
3845 // remove trailing spaces from program
3846 kwsys_stl::string::size_type pos = program.size()-1;
3847 while(program[pos] == ' ')
3849 program.erase(pos);
3850 pos--;
3852 args = dir.substr(spacePos, dir.size()-spacePos);
3853 return;
3855 // Now try and find the the program in the path
3856 findProg = SystemTools::FindProgram(tryProg.c_str(), e);
3857 if(findProg.size())
3859 program = findProg;
3860 // remove trailing spaces from program
3861 kwsys_stl::string::size_type pos = program.size()-1;
3862 while(program[pos] == ' ')
3864 program.erase(pos);
3865 pos--;
3867 args = dir.substr(spacePos, dir.size()-spacePos);
3868 return;
3870 // move past the space for the next search
3871 spacePos--;
3872 spacePos = dir.rfind(' ', spacePos);
3875 program = "";
3876 args = "";
3879 kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format)
3881 char buf[1024];
3882 time_t t;
3883 time(&t);
3884 strftime(buf, sizeof(buf), format, localtime(&t));
3885 return kwsys_stl::string(buf);
3888 kwsys_stl::string SystemTools::MakeCindentifier(const char* s)
3890 kwsys_stl::string str(s);
3891 if (str.find_first_of("0123456789") == 0)
3893 str = "_" + str;
3896 kwsys_stl::string permited_chars("_"
3897 "abcdefghijklmnopqrstuvwxyz"
3898 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3899 "0123456789");
3900 kwsys_stl::string::size_type pos = 0;
3901 while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_stl::string::npos)
3903 str[pos] = '_';
3905 return str;
3908 // Due to a buggy stream library on the HP and another on Mac OS X, we
3909 // need this very carefully written version of getline. Returns true
3910 // if any data were read before the end-of-file was reached.
3911 bool SystemTools::GetLineFromStream(kwsys_ios::istream& is,
3912 kwsys_stl::string& line,
3913 bool* has_newline /* = 0 */,
3914 long sizeLimit /* = -1 */)
3916 const int bufferSize = 1024;
3917 char buffer[bufferSize];
3918 bool haveData = false;
3919 bool haveNewline = false;
3921 // Start with an empty line.
3922 line = "";
3924 long leftToRead = sizeLimit;
3926 // If no characters are read from the stream, the end of file has
3927 // been reached. Clear the fail bit just before reading.
3928 while(!haveNewline &&
3929 leftToRead != 0 &&
3930 (is.clear(is.rdstate() & ~kwsys_ios::ios::failbit),
3931 is.getline(buffer, bufferSize), is.gcount() > 0))
3933 // We have read at least one byte.
3934 haveData = true;
3936 // If newline character was read the gcount includes the character
3937 // but the buffer does not: the end of line has been reached.
3938 size_t length = strlen(buffer);
3939 if(length < static_cast<size_t>(is.gcount()))
3941 haveNewline = true;
3944 // Avoid storing a carriage return character.
3945 if(length > 0 && buffer[length-1] == '\r')
3947 buffer[length-1] = 0;
3950 // if we read too much then truncate the buffer
3951 if (leftToRead > 0)
3953 if (static_cast<long>(length) > leftToRead)
3955 buffer[leftToRead-1] = 0;
3956 leftToRead = 0;
3958 else
3960 leftToRead -= static_cast<long>(length);
3964 // Append the data read to the line.
3965 line.append(buffer);
3966 sizeLimit = sizeLimit - static_cast<long>(length);
3969 // Return the results.
3970 if(has_newline)
3972 *has_newline = haveNewline;
3974 return haveData;
3977 int SystemTools::GetTerminalWidth()
3979 int width = -1;
3980 #ifdef HAVE_TTY_INFO
3981 struct winsize ws;
3982 char *columns; /* Unix98 environment variable */
3983 if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0)
3985 width = ws.ws_col;
3987 if(!isatty(STDOUT_FILENO))
3989 width = -1;
3991 columns = getenv("COLUMNS");
3992 if(columns && *columns)
3994 long t;
3995 char *endptr;
3996 t = strtol(columns, &endptr, 0);
3997 if(endptr && !*endptr && (t>0) && (t<1000))
3999 width = static_cast<int>(t);
4002 if ( width < 9 )
4004 width = -1;
4006 #endif
4007 return width;
4010 bool SystemTools::GetPermissions(const char* file, mode_t& mode)
4012 if ( !file )
4014 return false;
4017 struct stat st;
4018 if ( stat(file, &st) < 0 )
4020 return false;
4022 mode = st.st_mode;
4023 return true;
4026 bool SystemTools::SetPermissions(const char* file, mode_t mode)
4028 if ( !file )
4030 return false;
4032 if ( !SystemTools::FileExists(file) )
4034 return false;
4036 if ( chmod(file, mode) < 0 )
4038 return false;
4041 return true;
4044 kwsys_stl::string SystemTools::GetParentDirectory(const char* fileOrDir)
4046 return SystemTools::GetFilenamePath(fileOrDir);
4049 bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir)
4051 if(!*cDir)
4053 return false;
4055 kwsys_stl::string subdir = cSubdir;
4056 kwsys_stl::string dir = cDir;
4057 SystemTools::ConvertToUnixSlashes(dir);
4058 kwsys_stl::string path = subdir;
4061 path = SystemTools::GetParentDirectory(path.c_str());
4062 if(SystemTools::ComparePath(dir.c_str(), path.c_str()))
4064 return true;
4067 while ( path.size() > dir.size() );
4068 return false;
4071 void SystemTools::Delay(unsigned int msec)
4073 #ifdef _WIN32
4074 Sleep(msec);
4075 #else
4076 // The sleep function gives 1 second resolution and the usleep
4077 // function gives 1e-6 second resolution but on some platforms has a
4078 // maximum sleep time of 1 second. This could be re-implemented to
4079 // use select with masked signals or pselect to mask signals
4080 // atomically. If select is given empty sets and zero as the max
4081 // file descriptor but a non-zero timeout it can be used to block
4082 // for a precise amount of time.
4083 if(msec >= 1000)
4085 sleep(msec / 1000);
4086 usleep((msec % 1000) * 1000);
4088 else
4090 usleep(msec * 1000);
4092 #endif
4095 void SystemTools::ConvertWindowsCommandLineToUnixArguments(
4096 const char *cmd_line, int *argc, char ***argv)
4098 if (!cmd_line || !argc || !argv)
4100 return;
4103 // A space delimites an argument except when it is inside a quote
4105 (*argc) = 1;
4107 size_t cmd_line_len = strlen(cmd_line);
4109 size_t i;
4110 for (i = 0; i < cmd_line_len; i++)
4112 while (isspace(cmd_line[i]) && i < cmd_line_len)
4114 i++;
4116 if (i < cmd_line_len)
4118 if (cmd_line[i] == '\"')
4120 i++;
4121 while (cmd_line[i] != '\"' && i < cmd_line_len)
4123 i++;
4125 (*argc)++;
4127 else
4129 while (!isspace(cmd_line[i]) && i < cmd_line_len)
4131 i++;
4133 (*argc)++;
4138 (*argv) = new char* [(*argc) + 1];
4139 (*argv)[(*argc)] = NULL;
4141 // Set the first arg to be the exec name
4143 (*argv)[0] = new char [1024];
4144 #ifdef _WIN32
4145 ::GetModuleFileName(0, (*argv)[0], 1024);
4146 #else
4147 (*argv)[0][0] = '\0';
4148 #endif
4150 // Allocate the others
4152 int j;
4153 for (j = 1; j < (*argc); j++)
4155 (*argv)[j] = new char [cmd_line_len + 10];
4158 // Grab the args
4160 size_t pos;
4161 int argc_idx = 1;
4163 for (i = 0; i < cmd_line_len; i++)
4165 while (isspace(cmd_line[i]) && i < cmd_line_len)
4167 i++;
4169 if (i < cmd_line_len)
4171 if (cmd_line[i] == '\"')
4173 i++;
4174 pos = i;
4175 while (cmd_line[i] != '\"' && i < cmd_line_len)
4177 i++;
4179 memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
4180 (*argv)[argc_idx][i - pos] = '\0';
4181 argc_idx++;
4183 else
4185 pos = i;
4186 while (!isspace(cmd_line[i]) && i < cmd_line_len)
4188 i++;
4190 memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
4191 (*argv)[argc_idx][i - pos] = '\0';
4192 argc_idx++;
4198 kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
4200 kwsys_stl::string res;
4202 #ifdef _WIN32
4203 char buffer[256];
4205 OSVERSIONINFOEX osvi;
4206 BOOL bOsVersionInfoEx;
4208 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
4209 // If that fails, try using the OSVERSIONINFO structure.
4211 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
4212 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
4214 bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
4215 if (!bOsVersionInfoEx)
4217 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
4218 if (!GetVersionEx((OSVERSIONINFO *)&osvi))
4220 return 0;
4224 switch (osvi.dwPlatformId)
4226 // Test for the Windows NT product family.
4228 case VER_PLATFORM_WIN32_NT:
4230 // Test for the specific product family.
4232 if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
4234 #if (_MSC_VER >= 1300)
4235 if (osvi.wProductType == VER_NT_WORKSTATION)
4237 res += "Microsoft Windows Vista";
4239 else
4241 res += "Microsoft Windows Server 2008 family";
4243 #else
4244 res += "Microsoft Windows Vista or Windows Server 2008";
4245 #endif
4248 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
4250 res += "Microsoft Windows Server 2003 family";
4253 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
4255 res += "Microsoft Windows XP";
4258 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
4260 res += "Microsoft Windows 2000";
4263 if (osvi.dwMajorVersion <= 4)
4265 res += "Microsoft Windows NT";
4268 // Test for specific product on Windows NT 4.0 SP6 and later.
4270 if (bOsVersionInfoEx)
4272 // Test for the workstation type.
4274 #if (_MSC_VER >= 1300)
4275 if (osvi.wProductType == VER_NT_WORKSTATION)
4277 if (osvi.dwMajorVersion == 4)
4279 res += " Workstation 4.0";
4281 else if (osvi.dwMajorVersion == 5)
4283 if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
4285 res += " Home Edition";
4287 else
4289 res += " Professional";
4294 // Test for the server type.
4296 else if (osvi.wProductType == VER_NT_SERVER)
4298 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
4300 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
4302 res += " Datacenter Edition";
4304 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4306 res += " Enterprise Edition";
4308 else if (osvi.wSuiteMask == VER_SUITE_BLADE)
4310 res += " Web Edition";
4312 else
4314 res += " Standard Edition";
4318 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
4320 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
4322 res += " Datacenter Server";
4324 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4326 res += " Advanced Server";
4328 else
4330 res += " Server";
4334 else if (osvi.dwMajorVersion <= 4) // Windows NT 4.0
4336 if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
4338 res += " Server 4.0, Enterprise Edition";
4340 else
4342 res += " Server 4.0";
4346 #endif // Visual Studio 7 and up
4349 // Test for specific product on Windows NT 4.0 SP5 and earlier
4351 else
4353 HKEY hKey;
4354 #define BUFSIZE 80
4355 char szProductType[BUFSIZE];
4356 DWORD dwBufLen=BUFSIZE;
4357 LONG lRet;
4359 lRet = RegOpenKeyEx(
4360 HKEY_LOCAL_MACHINE,
4361 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
4362 0, KEY_QUERY_VALUE, &hKey);
4363 if (lRet != ERROR_SUCCESS)
4365 return 0;
4368 lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL,
4369 (LPBYTE) szProductType, &dwBufLen);
4371 if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
4373 return 0;
4376 RegCloseKey(hKey);
4378 if (lstrcmpi("WINNT", szProductType) == 0)
4380 res += " Workstation";
4382 if (lstrcmpi("LANMANNT", szProductType) == 0)
4384 res += " Server";
4386 if (lstrcmpi("SERVERNT", szProductType) == 0)
4388 res += " Advanced Server";
4391 res += " ";
4392 sprintf(buffer, "%ld", osvi.dwMajorVersion);
4393 res += buffer;
4394 res += ".";
4395 sprintf(buffer, "%ld", osvi.dwMinorVersion);
4396 res += buffer;
4399 // Display service pack (if any) and build number.
4401 if (osvi.dwMajorVersion == 4 &&
4402 lstrcmpi(osvi.szCSDVersion, "Service Pack 6") == 0)
4404 HKEY hKey;
4405 LONG lRet;
4407 // Test for SP6 versus SP6a.
4409 lRet = RegOpenKeyEx(
4410 HKEY_LOCAL_MACHINE,
4411 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
4412 0, KEY_QUERY_VALUE, &hKey);
4414 if (lRet == ERROR_SUCCESS)
4416 res += " Service Pack 6a (Build ";
4417 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4418 res += buffer;
4419 res += ")";
4421 else // Windows NT 4.0 prior to SP6a
4423 res += " ";
4424 res += osvi.szCSDVersion;
4425 res += " (Build ";
4426 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4427 res += buffer;
4428 res += ")";
4431 RegCloseKey(hKey);
4433 else // Windows NT 3.51 and earlier or Windows 2000 and later
4435 res += " ";
4436 res += osvi.szCSDVersion;
4437 res += " (Build ";
4438 sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
4439 res += buffer;
4440 res += ")";
4443 break;
4445 // Test for the Windows 95 product family.
4447 case VER_PLATFORM_WIN32_WINDOWS:
4449 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
4451 res += "Microsoft Windows 95";
4452 if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
4454 res += " OSR2";
4458 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
4460 res += "Microsoft Windows 98";
4461 if (osvi.szCSDVersion[1] == 'A')
4463 res += " SE";
4467 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
4469 res += "Microsoft Windows Millennium Edition";
4471 break;
4473 case VER_PLATFORM_WIN32s:
4475 res += "Microsoft Win32s";
4476 break;
4478 #endif
4480 return res;
4483 // ----------------------------------------------------------------------
4484 bool SystemTools::ParseURLProtocol( const kwsys_stl::string& URL,
4485 kwsys_stl::string& protocol,
4486 kwsys_stl::string& dataglom )
4488 // match 0 entire url
4489 // match 1 protocol
4490 // match 2 dataglom following protocol://
4491 kwsys::RegularExpression urlRe( VTK_URL_PROTOCOL_REGEX );
4493 if ( ! urlRe.find( URL ) ) return false;
4495 protocol = urlRe.match( 1 );
4496 dataglom = urlRe.match( 2 );
4498 return true;
4501 // ----------------------------------------------------------------------
4502 bool SystemTools::ParseURL( const kwsys_stl::string& URL,
4503 kwsys_stl::string& protocol,
4504 kwsys_stl::string& username,
4505 kwsys_stl::string& password,
4506 kwsys_stl::string& hostname,
4507 kwsys_stl::string& dataport,
4508 kwsys_stl::string& database )
4510 kwsys::RegularExpression urlRe( VTK_URL_REGEX );
4511 if ( ! urlRe.find( URL ) ) return false;
4513 // match 0 URL
4514 // match 1 protocol
4515 // match 2 mangled user
4516 // match 3 username
4517 // match 4 mangled password
4518 // match 5 password
4519 // match 6 hostname
4520 // match 7 mangled port
4521 // match 8 dataport
4522 // match 9 database name
4524 protocol = urlRe.match( 1 );
4525 username = urlRe.match( 3 );
4526 password = urlRe.match( 5 );
4527 hostname = urlRe.match( 6 );
4528 dataport = urlRe.match( 8 );
4529 database = urlRe.match( 9 );
4531 return true;
4534 // ----------------------------------------------------------------------
4535 // These must NOT be initialized. Default initialization to zero is
4536 // necessary.
4537 unsigned int SystemToolsManagerCount;
4538 SystemToolsTranslationMap *SystemTools::TranslationMap;
4539 SystemToolsTranslationMap *SystemTools::LongPathMap;
4541 // SystemToolsManager manages the SystemTools singleton.
4542 // SystemToolsManager should be included in any translation unit
4543 // that will use SystemTools or that implements the singleton
4544 // pattern. It makes sure that the SystemTools singleton is created
4545 // before and destroyed after all other singletons in CMake.
4547 SystemToolsManager::SystemToolsManager()
4549 if(++SystemToolsManagerCount == 1)
4551 SystemTools::ClassInitialize();
4555 SystemToolsManager::~SystemToolsManager()
4557 if(--SystemToolsManagerCount == 0)
4559 SystemTools::ClassFinalize();
4563 #if defined(__VMS)
4564 // On VMS we configure the run time C library to be more UNIX like.
4565 // http://h71000.www7.hp.com/doc/732final/5763/5763pro_004.html
4566 extern "C" int decc$feature_get_index(char *name);
4567 extern "C" int decc$feature_set_value(int index, int mode, int value);
4568 static int SetVMSFeature(char* name, int value)
4570 int i;
4571 errno = 0;
4572 i = decc$feature_get_index(name);
4573 return i >= 0 && (decc$feature_set_value(i, 1, value) >= 0 || errno == 0);
4575 #endif
4577 void SystemTools::ClassInitialize()
4579 #ifdef __VMS
4580 SetVMSFeature("DECC$FILENAME_UNIX_ONLY", 1);
4581 #endif
4582 // Allocate the translation map first.
4583 SystemTools::TranslationMap = new SystemToolsTranslationMap;
4584 SystemTools::LongPathMap = new SystemToolsTranslationMap;
4586 // Add some special translation paths for unix. These are not added
4587 // for windows because drive letters need to be maintained. Also,
4588 // there are not sym-links and mount points on windows anyway.
4589 #if !defined(_WIN32) || defined(__CYGWIN__)
4590 // Work-around an SGI problem by always adding this mapping:
4591 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
4592 // The tmp path is frequently a logical path so always keep it:
4593 SystemTools::AddKeepPath("/tmp/");
4595 // If the current working directory is a logical path then keep the
4596 // logical name.
4597 if(const char* pwd = getenv("PWD"))
4599 char buf[2048];
4600 if(const char* cwd = Getcwd(buf, 2048))
4602 // The current working directory may be a logical path. Find
4603 // the shortest logical path that still produces the correct
4604 // physical path.
4605 kwsys_stl::string cwd_changed;
4606 kwsys_stl::string pwd_changed;
4608 // Test progressively shorter logical-to-physical mappings.
4609 kwsys_stl::string pwd_str = pwd;
4610 kwsys_stl::string cwd_str = cwd;
4611 kwsys_stl::string pwd_path;
4612 Realpath(pwd, pwd_path);
4613 while(cwd_str == pwd_path && cwd_str != pwd_str)
4615 // The current pair of paths is a working logical mapping.
4616 cwd_changed = cwd_str;
4617 pwd_changed = pwd_str;
4619 // Strip off one directory level and see if the logical
4620 // mapping still works.
4621 pwd_str = SystemTools::GetFilenamePath(pwd_str.c_str());
4622 cwd_str = SystemTools::GetFilenamePath(cwd_str.c_str());
4623 Realpath(pwd_str.c_str(), pwd_path);
4626 // Add the translation to keep the logical path name.
4627 if(!cwd_changed.empty() && !pwd_changed.empty())
4629 SystemTools::AddTranslationPath(cwd_changed.c_str(),
4630 pwd_changed.c_str());
4634 #endif
4637 void SystemTools::ClassFinalize()
4639 delete SystemTools::TranslationMap;
4640 delete SystemTools::LongPathMap;
4644 } // namespace KWSYS_NAMESPACE
4646 #if defined(_MSC_VER) && defined(_DEBUG)
4647 # include <crtdbg.h>
4648 # include <stdio.h>
4649 # include <stdlib.h>
4650 namespace KWSYS_NAMESPACE
4653 static int SystemToolsDebugReport(int, char* message, int*)
4655 fprintf(stderr, "%s", message);
4656 fflush(stderr);
4657 return 1; // no further reporting required
4660 void SystemTools::EnableMSVCDebugHook()
4662 if (getenv("DART_TEST_FROM_DART"))
4664 _CrtSetReportHook(SystemToolsDebugReport);
4668 } // namespace KWSYS_NAMESPACE
4669 #else
4670 namespace KWSYS_NAMESPACE
4672 void SystemTools::EnableMSVCDebugHook() {}
4673 } // namespace KWSYS_NAMESPACE
4674 #endif