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.
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"
34 # pragma warning (disable: 4786)
37 #if defined(__sgi) && !defined(__GNUC__)
38 # pragma set woff 1375 /* base class destructor not virtual */
44 # include <malloc.h> /* for malloc/free on QNX */
52 // support for realpath call
56 #include <sys/param.h>
58 #include <sys/ioctl.h>
62 #include <signal.h> /* sigprocmask */
65 // Windows API. Some parts used even on cygwin.
70 // getpwnam doesn't exist on Windows and Cray Xt3/Catamount
71 // same for TIOCGWINSZ
72 #if defined(_WIN32) || defined (__LIBCATAMOUNT__)
76 # define HAVE_GETPWNAM 1
77 # define HAVE_TTY_INFO 1
80 #define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)"
81 #define VTK_URL_REGEX "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/(.+)?"
84 #include <sys/utime.h>
90 // This is a hack to prevent warnings about these functions being
91 // declared but not referenced.
92 #if defined(__sgi) && !defined(__GNUC__)
93 # include <sys/termios.h>
94 namespace KWSYS_NAMESPACE
101 Ref1
= sizeof(cfgetospeed(0)),
102 Ref2
= sizeof(cfgetispeed(0)),
103 Ref3
= sizeof(tcgetattr(0, 0)),
104 Ref4
= sizeof(tcsetattr(0, 0, 0)),
105 Ref5
= sizeof(cfsetospeed(0,0)),
106 Ref6
= sizeof(cfsetispeed(0,0))
112 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) ||defined(__BORLANDC__) || defined(__MINGW32__))
115 #define _unlink unlink
118 /* The maximum length of a file name. */
119 #if defined(PATH_MAX)
120 # define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
121 #elif defined(MAXPATHLEN)
122 # define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
124 # define KWSYS_SYSTEMTOOLS_MAXPATH 16384
126 #if defined(__WATCOMC__)
130 #define _getcwd getcwd
134 #if defined(__HAIKU__)
135 #include <os/kernel/OS.h>
136 #include <os/storage/Path.h>
139 #if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
140 #include <be/kernel/OS.h>
141 #include <be/storage/Path.h>
143 // BeOS 5 doesn't have usleep(), but it has snooze(), which is identical.
144 static inline void usleep(unsigned int msec
)
149 // BeOS 5 also doesn't have realpath(), but its C++ API offers something close.
150 static inline char *realpath(const char *path
, char *resolved_path
)
152 const size_t maxlen
= KWSYS_SYSTEMTOOLS_MAXPATH
;
153 snprintf(resolved_path
, maxlen
, "%s", path
);
154 BPath
normalized(resolved_path
, NULL
, true);
155 const char *resolved
= normalized
.Path();
156 if (resolved
!= NULL
) // NULL == No such file.
158 if (snprintf(resolved_path
, maxlen
, "%s", resolved
) < maxlen
)
160 return resolved_path
;
163 return NULL
; // something went wrong.
167 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
168 inline int Mkdir(const char* dir
)
172 inline int Rmdir(const char* dir
)
176 inline const char* Getcwd(char* buf
, unsigned int len
)
178 const char* ret
= _getcwd(buf
, len
);
181 fprintf(stderr
, "No current working directory.\n");
184 // make sure the drive letter is capital
185 if(strlen(buf
) > 1 && buf
[1] == ':')
187 buf
[0] = toupper(buf
[0]);
191 inline int Chdir(const char* dir
)
193 #if defined(__BORLANDC__)
199 inline void Realpath(const char *path
, kwsys_stl::string
& resolved_path
)
202 char fullpath
[MAX_PATH
];
203 if( GetFullPathName(path
, sizeof(fullpath
), fullpath
, &ptemp
) )
205 resolved_path
= fullpath
;
206 KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path
);
210 #include <sys/types.h>
213 inline int Mkdir(const char* dir
)
215 return mkdir(dir
, 00777);
217 inline int Rmdir(const char* dir
)
221 inline const char* Getcwd(char* buf
, unsigned int len
)
223 const char* ret
= getcwd(buf
, len
);
226 fprintf(stderr
, "No current working directory\n");
232 inline int Chdir(const char* dir
)
236 inline void Realpath(const char *path
, kwsys_stl::string
& resolved_path
)
238 char resolved_name
[KWSYS_SYSTEMTOOLS_MAXPATH
];
240 realpath(path
, resolved_name
);
241 resolved_path
= resolved_name
;
245 #if !defined(_WIN32) && defined(__COMO__)
246 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
249 extern FILE *popen (__const
char *__command
, __const
char *__modes
) __THROW
;
250 extern int pclose (FILE *__stream
) __THROW
;
251 extern char *realpath (__const
char *__restrict __name
,
252 char *__restrict __resolved
) __THROW
;
253 extern char *strdup (__const
char *__s
) __THROW
;
254 extern int putenv (char *__string
) __THROW
;
258 /* Implement floattime() for various platforms */
259 // Taken from Python 2.1.3
261 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
262 # include <sys/timeb.h>
264 # if defined( __BORLANDC__)
267 # else // Visual studio?
268 # define FTIME _ftime
269 # define TIMEB _timeb
271 #elif defined( __CYGWIN__ ) || defined( __linux__ )
272 # include <sys/time.h>
274 # define HAVE_GETTIMEOFDAY
277 namespace KWSYS_NAMESPACE
280 class SystemToolsTranslationMap
:
281 public kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>
287 SystemTools::GetTime(void)
289 /* There are three ways to get the time:
290 (1) gettimeofday() -- resolution in microseconds
291 (2) ftime() -- resolution in milliseconds
292 (3) time() -- resolution in seconds
293 In all cases the return value is a float in seconds.
294 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
295 fail, so we fall back on ftime() or time().
296 Note: clock resolution does not imply clock accuracy! */
297 #ifdef HAVE_GETTIMEOFDAY
300 #ifdef GETTIMEOFDAY_NO_TZ
301 if (gettimeofday(&t
) == 0)
302 return static_cast<double>(t
.tv_sec
) + t
.tv_usec
*0.000001;
303 #else /* !GETTIMEOFDAY_NO_TZ */
304 if (gettimeofday(&t
, static_cast<struct timezone
*>(NULL
)) == 0)
305 return static_cast<double>(t
.tv_sec
) + t
.tv_usec
*0.000001;
306 #endif /* !GETTIMEOFDAY_NO_TZ */
308 #endif /* !HAVE_GETTIMEOFDAY */
310 #if defined(HAVE_FTIME)
313 return static_cast<double>(t
.time
) +
314 static_cast<double>(t
.millitm
) * static_cast<double>(0.001);
315 #else /* !HAVE_FTIME */
318 return static_cast<double>(secs
);
319 #endif /* !HAVE_FTIME */
323 // adds the elements of the env variable path to the arg passed in
324 void SystemTools::GetPath(kwsys_stl::vector
<kwsys_stl::string
>& path
, const char* env
)
326 #if defined(_WIN32) && !defined(__CYGWIN__)
327 const char* pathSep
= ";";
329 const char* pathSep
= ":";
335 const char* cpathEnv
= SystemTools::GetEnv(env
);
341 kwsys_stl::string pathEnv
= cpathEnv
;
343 // A hack to make the below algorithm work.
344 if(pathEnv
[pathEnv
.length()-1] != ':')
348 kwsys_stl::string::size_type start
=0;
352 kwsys_stl::string::size_type endpos
= pathEnv
.find(pathSep
, start
);
353 if(endpos
!= kwsys_stl::string::npos
)
355 kwsys_stl::string convertedPath
;
356 Realpath(pathEnv
.substr(start
, endpos
-start
).c_str(), convertedPath
);
357 path
.push_back(convertedPath
);
365 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
366 i
!= path
.end(); ++i
)
368 SystemTools::ConvertToUnixSlashes(*i
);
372 const char* SystemTools::GetEnv(const char* key
)
377 bool SystemTools::GetEnv(const char* key
, kwsys_stl::string
& result
)
379 const char* v
= getenv(key
);
391 const char* SystemTools::GetExecutableExtension()
393 #if defined(_WIN32) || defined(__CYGWIN__)
401 bool SystemTools::MakeDirectory(const char* path
)
407 if(SystemTools::FileExists(path
))
411 kwsys_stl::string dir
= path
;
416 SystemTools::ConvertToUnixSlashes(dir
);
418 kwsys_stl::string::size_type pos
= dir
.find(':');
419 if(pos
== kwsys_stl::string::npos
)
423 kwsys_stl::string topdir
;
424 while((pos
= dir
.find('/', pos
)) != kwsys_stl::string::npos
)
426 topdir
= dir
.substr(0, pos
);
427 Mkdir(topdir
.c_str());
430 if(dir
[dir
.size()-1] == '/')
432 topdir
= dir
.substr(0, dir
.size());
438 if(Mkdir(topdir
.c_str()) != 0)
440 // There is a bug in the Borland Run time library which makes MKDIR
441 // return EACCES when it should return EEXISTS
442 // if it is some other error besides directory exists
444 if( (errno
!= EEXIST
)
457 // replace replace with with as many times as it shows up in source.
458 // write the result into source.
459 void SystemTools::ReplaceString(kwsys_stl::string
& source
,
463 const char *src
= source
.c_str();
464 char *searchPos
= const_cast<char *>(strstr(src
,replace
));
466 // get out quick if string is not found
472 // perform replacements until done
473 size_t replaceSize
= strlen(replace
);
474 // do while hangs if replaceSize is 0
479 char *orig
= strdup(src
);
480 char *currentPos
= orig
;
481 searchPos
= searchPos
- src
+ orig
;
483 // initialize the result
484 source
.erase(source
.begin(),source
.end());
488 source
+= currentPos
;
489 currentPos
= searchPos
+ replaceSize
;
492 searchPos
= strstr(currentPos
,replace
);
496 // copy any trailing text
497 source
+= currentPos
;
501 #if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
502 # define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
503 # define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
505 # define KWSYS_ST_KEY_WOW64_32KEY 0x0200
506 # define KWSYS_ST_KEY_WOW64_64KEY 0x0100
509 #if defined(_WIN32) && !defined(__CYGWIN__)
510 static DWORD
SystemToolsMakeRegistryMode(DWORD mode
,
511 SystemTools::KeyWOW64 view
)
513 if(view
== SystemTools::KeyWOW64_32
)
515 return mode
| KWSYS_ST_KEY_WOW64_32KEY
;
517 else if(view
== SystemTools::KeyWOW64_64
)
519 return mode
| KWSYS_ST_KEY_WOW64_64KEY
;
525 // Read a registry value.
527 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
528 // => will return the data of the "default" value of the key
529 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
530 // => will return the data of the "Root" value of the key
532 #if defined(_WIN32) && !defined(__CYGWIN__)
533 bool SystemTools::ReadRegistryValue(const char *key
, kwsys_stl::string
&value
,
536 bool valueset
= false;
537 kwsys_stl::string primary
= key
;
538 kwsys_stl::string second
;
539 kwsys_stl::string valuename
;
541 size_t start
= primary
.find("\\");
542 if (start
== kwsys_stl::string::npos
)
547 size_t valuenamepos
= primary
.find(";");
548 if (valuenamepos
!= kwsys_stl::string::npos
)
550 valuename
= primary
.substr(valuenamepos
+1);
553 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
554 primary
= primary
.substr(0, start
);
556 HKEY primaryKey
= HKEY_CURRENT_USER
;
557 if (primary
== "HKEY_CURRENT_USER")
559 primaryKey
= HKEY_CURRENT_USER
;
561 if (primary
== "HKEY_CURRENT_CONFIG")
563 primaryKey
= HKEY_CURRENT_CONFIG
;
565 if (primary
== "HKEY_CLASSES_ROOT")
567 primaryKey
= HKEY_CLASSES_ROOT
;
569 if (primary
== "HKEY_LOCAL_MACHINE")
571 primaryKey
= HKEY_LOCAL_MACHINE
;
573 if (primary
== "HKEY_USERS")
575 primaryKey
= HKEY_USERS
;
579 if(RegOpenKeyEx(primaryKey
,
582 SystemToolsMakeRegistryMode(KEY_READ
, view
),
583 &hKey
) != ERROR_SUCCESS
)
589 DWORD dwType
, dwSize
;
592 if(RegQueryValueEx(hKey
,
593 (LPTSTR
)valuename
.c_str(),
597 &dwSize
) == ERROR_SUCCESS
)
599 if (dwType
== REG_SZ
)
604 else if (dwType
== REG_EXPAND_SZ
)
607 DWORD dwExpandedSize
= sizeof(expanded
)/sizeof(expanded
[0]);
608 if(ExpandEnvironmentStrings(data
, expanded
, dwExpandedSize
))
622 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string
&,
630 // Write a registry value.
632 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
633 // => will set the data of the "default" value of the key
634 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
635 // => will set the data of the "Root" value of the key
637 #if defined(_WIN32) && !defined(__CYGWIN__)
638 bool SystemTools::WriteRegistryValue(const char *key
, const char *value
,
641 kwsys_stl::string primary
= key
;
642 kwsys_stl::string second
;
643 kwsys_stl::string valuename
;
645 size_t start
= primary
.find("\\");
646 if (start
== kwsys_stl::string::npos
)
651 size_t valuenamepos
= primary
.find(";");
652 if (valuenamepos
!= kwsys_stl::string::npos
)
654 valuename
= primary
.substr(valuenamepos
+1);
657 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
658 primary
= primary
.substr(0, start
);
660 HKEY primaryKey
= HKEY_CURRENT_USER
;
661 if (primary
== "HKEY_CURRENT_USER")
663 primaryKey
= HKEY_CURRENT_USER
;
665 if (primary
== "HKEY_CURRENT_CONFIG")
667 primaryKey
= HKEY_CURRENT_CONFIG
;
669 if (primary
== "HKEY_CLASSES_ROOT")
671 primaryKey
= HKEY_CLASSES_ROOT
;
673 if (primary
== "HKEY_LOCAL_MACHINE")
675 primaryKey
= HKEY_LOCAL_MACHINE
;
677 if (primary
== "HKEY_USERS")
679 primaryKey
= HKEY_USERS
;
684 if(RegCreateKeyEx(primaryKey
,
688 REG_OPTION_NON_VOLATILE
,
689 SystemToolsMakeRegistryMode(KEY_WRITE
, view
),
692 &dwDummy
) != ERROR_SUCCESS
)
697 if(RegSetValueEx(hKey
,
698 (LPTSTR
)valuename
.c_str(),
702 (DWORD
)(strlen(value
) + 1)) == ERROR_SUCCESS
)
709 bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64
)
715 // Delete a registry value.
717 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
718 // => will delete the data of the "default" value of the key
719 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
720 // => will delete the data of the "Root" value of the key
722 #if defined(_WIN32) && !defined(__CYGWIN__)
723 bool SystemTools::DeleteRegistryValue(const char *key
, KeyWOW64 view
)
725 kwsys_stl::string primary
= key
;
726 kwsys_stl::string second
;
727 kwsys_stl::string valuename
;
729 size_t start
= primary
.find("\\");
730 if (start
== kwsys_stl::string::npos
)
735 size_t valuenamepos
= primary
.find(";");
736 if (valuenamepos
!= kwsys_stl::string::npos
)
738 valuename
= primary
.substr(valuenamepos
+1);
741 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
742 primary
= primary
.substr(0, start
);
744 HKEY primaryKey
= HKEY_CURRENT_USER
;
745 if (primary
== "HKEY_CURRENT_USER")
747 primaryKey
= HKEY_CURRENT_USER
;
749 if (primary
== "HKEY_CURRENT_CONFIG")
751 primaryKey
= HKEY_CURRENT_CONFIG
;
753 if (primary
== "HKEY_CLASSES_ROOT")
755 primaryKey
= HKEY_CLASSES_ROOT
;
757 if (primary
== "HKEY_LOCAL_MACHINE")
759 primaryKey
= HKEY_LOCAL_MACHINE
;
761 if (primary
== "HKEY_USERS")
763 primaryKey
= HKEY_USERS
;
767 if(RegOpenKeyEx(primaryKey
,
770 SystemToolsMakeRegistryMode(KEY_WRITE
, view
),
771 &hKey
) != ERROR_SUCCESS
)
777 if(RegDeleteValue(hKey
,
778 (LPTSTR
)valuename
.c_str()) == ERROR_SUCCESS
)
787 bool SystemTools::DeleteRegistryValue(const char *, KeyWOW64
)
793 bool SystemTools::SameFile(const char* file1
, const char* file2
)
796 HANDLE hFile1
, hFile2
;
798 hFile1
= CreateFile( file1
,
803 FILE_FLAG_BACKUP_SEMANTICS
,
806 hFile2
= CreateFile( file2
,
811 FILE_FLAG_BACKUP_SEMANTICS
,
814 if( hFile1
== INVALID_HANDLE_VALUE
|| hFile2
== INVALID_HANDLE_VALUE
)
816 if(hFile1
!= INVALID_HANDLE_VALUE
)
820 if(hFile2
!= INVALID_HANDLE_VALUE
)
827 BY_HANDLE_FILE_INFORMATION fiBuf1
;
828 BY_HANDLE_FILE_INFORMATION fiBuf2
;
829 GetFileInformationByHandle( hFile1
, &fiBuf1
);
830 GetFileInformationByHandle( hFile2
, &fiBuf2
);
833 return (fiBuf1
.dwVolumeSerialNumber
== fiBuf2
.dwVolumeSerialNumber
&&
834 fiBuf1
.nFileIndexHigh
== fiBuf2
.nFileIndexHigh
&&
835 fiBuf1
.nFileIndexLow
== fiBuf2
.nFileIndexLow
);
837 struct stat fileStat1
, fileStat2
;
838 if (stat(file1
, &fileStat1
) == 0 && stat(file2
, &fileStat2
) == 0)
840 // see if the files are the same file
841 // check the device inode and size
842 if(memcmp(&fileStat2
.st_dev
, &fileStat1
.st_dev
, sizeof(fileStat1
.st_dev
)) == 0 &&
843 memcmp(&fileStat2
.st_ino
, &fileStat1
.st_ino
, sizeof(fileStat1
.st_ino
)) == 0 &&
844 fileStat2
.st_size
== fileStat1
.st_size
855 // return true if the file exists
856 bool SystemTools::FileExists(const char* filename
, bool isFile
)
859 # define access _access
866 if ((filename
!=0) && (*filename
== 0))
872 if ( access(filename
, R_OK
) != 0 )
878 // If isFile is set return not FileIsDirectory,
879 // so this will only be true if it is a file
882 return !SystemTools::FileIsDirectory(filename
);
888 bool SystemTools::Touch(const char* filename
, bool create
)
890 if(create
&& !SystemTools::FileExists(filename
))
892 FILE* file
= fopen(filename
, "a+b");
902 #define utimbuf _utimbuf
904 struct stat fromStat
;
905 if(stat(filename
, &fromStat
) < 0)
910 buf
.actime
= fromStat
.st_atime
;
911 buf
.modtime
= static_cast<time_t>(SystemTools::GetTime());
912 if(utime(filename
, &buf
) < 0)
919 bool SystemTools::FileTimeCompare(const char* f1
, const char* f2
,
922 // Default to same time.
924 #if !defined(_WIN32) || defined(__CYGWIN__)
925 // POSIX version. Use stat function to get file modification time.
927 if(stat(f1
, &s1
) != 0)
932 if(stat(f2
, &s2
) != 0)
936 # if KWSYS_STAT_HAS_ST_MTIM
937 // Compare using nanosecond resolution.
938 if(s1
.st_mtim
.tv_sec
< s2
.st_mtim
.tv_sec
)
942 else if(s1
.st_mtim
.tv_sec
> s2
.st_mtim
.tv_sec
)
946 else if(s1
.st_mtim
.tv_nsec
< s2
.st_mtim
.tv_nsec
)
950 else if(s1
.st_mtim
.tv_nsec
> s2
.st_mtim
.tv_nsec
)
955 // Compare using 1 second resolution.
956 if(s1
.st_mtime
< s2
.st_mtime
)
960 else if(s1
.st_mtime
> s2
.st_mtime
)
966 // Windows version. Get the modification time from extended file attributes.
967 WIN32_FILE_ATTRIBUTE_DATA f1d
;
968 WIN32_FILE_ATTRIBUTE_DATA f2d
;
969 if(!GetFileAttributesEx(f1
, GetFileExInfoStandard
, &f1d
))
973 if(!GetFileAttributesEx(f2
, GetFileExInfoStandard
, &f2d
))
978 // Compare the file times using resolution provided by system call.
979 *result
= (int)CompareFileTime(&f1d
.ftLastWriteTime
, &f2d
.ftLastWriteTime
);
985 // Return a capitalized string (i.e the first letter is uppercased, all other
987 kwsys_stl::string
SystemTools::Capitalized(const kwsys_stl::string
& s
)
995 n
[0] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[0]));
996 for (size_t i
= 1; i
< s
.size(); i
++)
998 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
1003 // Return capitalized words
1004 kwsys_stl::string
SystemTools::CapitalizedWords(const kwsys_stl::string
& s
)
1006 kwsys_stl::string
n(s
);
1007 for (size_t i
= 0; i
< s
.size(); i
++)
1009 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1010 // MS has an assert that will fail if s[i] < 0; setting
1011 // LC_CTYPE using setlocale() does *not* help. Painful.
1012 if ((int)s
[i
] >= 0 && isalpha(s
[i
]) &&
1013 (i
== 0 || ((int)s
[i
- 1] >= 0 && isspace(s
[i
- 1]))))
1015 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
1018 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
1024 // Return uncapitalized words
1025 kwsys_stl::string
SystemTools::UnCapitalizedWords(const kwsys_stl::string
& s
)
1027 kwsys_stl::string
n(s
);
1028 for (size_t i
= 0; i
< s
.size(); i
++)
1030 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1031 // MS has an assert that will fail if s[i] < 0; setting
1032 // LC_CTYPE using setlocale() does *not* help. Painful.
1033 if ((int)s
[i
] >= 0 && isalpha(s
[i
]) &&
1034 (i
== 0 || ((int)s
[i
- 1] >= 0 && isspace(s
[i
- 1]))))
1036 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
1039 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
1045 // only works for words with at least two letters
1046 kwsys_stl::string
SystemTools::AddSpaceBetweenCapitalizedWords(
1047 const kwsys_stl::string
& s
)
1049 kwsys_stl::string n
;
1052 n
.reserve(s
.size());
1054 for (size_t i
= 1; i
< s
.size(); i
++)
1056 if (isupper(s
[i
]) && !isspace(s
[i
- 1]) && !isupper(s
[i
- 1]))
1066 char* SystemTools::AppendStrings(const char* str1
, const char* str2
)
1070 return SystemTools::DuplicateString(str2
);
1074 return SystemTools::DuplicateString(str1
);
1076 size_t len1
= strlen(str1
);
1077 char *newstr
= new char[len1
+ strlen(str2
) + 1];
1082 strcpy(newstr
, str1
);
1083 strcat(newstr
+ len1
, str2
);
1087 char* SystemTools::AppendStrings(
1088 const char* str1
, const char* str2
, const char* str3
)
1092 return SystemTools::AppendStrings(str2
, str3
);
1096 return SystemTools::AppendStrings(str1
, str3
);
1100 return SystemTools::AppendStrings(str1
, str2
);
1103 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1104 char *newstr
= new char[len1
+ len2
+ strlen(str3
) + 1];
1109 strcpy(newstr
, str1
);
1110 strcat(newstr
+ len1
, str2
);
1111 strcat(newstr
+ len1
+ len2
, str3
);
1115 // Return a lower case string
1116 kwsys_stl::string
SystemTools::LowerCase(const kwsys_stl::string
& s
)
1118 kwsys_stl::string n
;
1120 for (size_t i
= 0; i
< s
.size(); i
++)
1122 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
1127 // Return a lower case string
1128 kwsys_stl::string
SystemTools::UpperCase(const kwsys_stl::string
& s
)
1130 kwsys_stl::string n
;
1132 for (size_t i
= 0; i
< s
.size(); i
++)
1134 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
1139 // Count char in string
1140 size_t SystemTools::CountChar(const char* str
, char c
)
1158 // Remove chars in string
1159 char* SystemTools::RemoveChars(const char* str
, const char *toremove
)
1165 char *clean_str
= new char [strlen(str
) + 1];
1166 char *ptr
= clean_str
;
1169 const char *str2
= toremove
;
1170 while (*str2
&& *str
!= *str2
)
1184 // Remove chars in string
1185 char* SystemTools::RemoveCharsButUpperHex(const char* str
)
1191 char *clean_str
= new char [strlen(str
) + 1];
1192 char *ptr
= clean_str
;
1195 if ((*str
>= '0' && *str
<= '9') || (*str
>= 'A' && *str
<= 'F'))
1205 // Replace chars in string
1206 char* SystemTools::ReplaceChars(char* str
, const char *toreplace
, char replacement
)
1213 const char *ptr2
= toreplace
;
1228 // Returns if string starts with another string
1229 bool SystemTools::StringStartsWith(const char* str1
, const char* str2
)
1235 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1236 return len1
>= len2
&& !strncmp(str1
, str2
, len2
) ? true : false;
1239 // Returns if string ends with another string
1240 bool SystemTools::StringEndsWith(const char* str1
, const char* str2
)
1246 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1247 return len1
>= len2
&& !strncmp(str1
+ (len1
- len2
), str2
, len2
) ? true : false;
1250 // Returns a pointer to the last occurence of str2 in str1
1251 const char* SystemTools::FindLastString(const char* str1
, const char* str2
)
1258 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1261 const char *ptr
= str1
+ len1
- len2
;
1264 if (!strncmp(ptr
, str2
, len2
))
1268 } while (ptr
-- != str1
);
1275 char* SystemTools::DuplicateString(const char* str
)
1279 char *newstr
= new char [strlen(str
) + 1];
1280 return strcpy(newstr
, str
);
1285 // Return a cropped string
1286 kwsys_stl::string
SystemTools::CropString(const kwsys_stl::string
& s
,
1289 if (!s
.size() || max_len
== 0 || max_len
>= s
.size())
1294 kwsys_stl::string n
;
1297 size_t middle
= max_len
/ 2;
1299 n
+= s
.substr(0, middle
);
1300 n
+= s
.substr(s
.size() - (max_len
- middle
), kwsys_stl::string::npos
);
1307 n
[middle
- 1] = '.';
1310 n
[middle
+ 1] = '.';
1318 //----------------------------------------------------------------------------
1319 kwsys_stl::vector
<kwsys::String
> SystemTools::SplitString(const char* p
, char sep
, bool isPath
)
1321 kwsys_stl::string path
= p
;
1322 kwsys_stl::vector
<kwsys::String
> paths
;
1323 if(isPath
&& path
[0] == '/')
1325 path
.erase(path
.begin());
1326 paths
.push_back("/");
1328 kwsys_stl::string::size_type pos1
= 0;
1329 kwsys_stl::string::size_type pos2
= path
.find(sep
, pos1
+1);
1330 while(pos2
!= kwsys_stl::string::npos
)
1332 paths
.push_back(path
.substr(pos1
, pos2
-pos1
));
1334 pos2
= path
.find(sep
, pos1
+1);
1336 paths
.push_back(path
.substr(pos1
, pos2
-pos1
));
1341 //----------------------------------------------------------------------------
1342 int SystemTools::EstimateFormatLength(const char *format
, va_list ap
)
1349 // Quick-hack attempt at estimating the length of the string.
1350 // Should never under-estimate.
1352 // Start with the length of the format string itself.
1354 size_t length
= strlen(format
);
1356 // Increase the length for every argument in the format.
1358 const char* cur
= format
;
1363 // Skip "%%" since it doesn't correspond to a va_arg.
1366 while(!int(isalpha(*cur
)))
1374 // Check the length of the string.
1375 char* s
= va_arg(ap
, char*);
1378 length
+= strlen(s
);
1385 // Assume the argument contributes no more than 64 characters.
1388 // Eat the argument.
1389 static_cast<void>(va_arg(ap
, double));
1393 // Assume the argument contributes no more than 64 characters.
1396 // Eat the argument.
1397 static_cast<void>(va_arg(ap
, int));
1402 // Move past the characters just tested.
1407 return static_cast<int>(length
);
1410 kwsys_stl::string
SystemTools::EscapeChars(
1412 const char *chars_to_escape
,
1415 kwsys_stl::string n
;
1418 if (!chars_to_escape
| !*chars_to_escape
)
1424 n
.reserve(strlen(str
));
1427 const char *ptr
= chars_to_escape
;
1445 // convert windows slashes to unix slashes
1446 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string
& path
)
1448 const char* pathCString
= path
.c_str();
1449 bool hasDoubleSlash
= false;
1451 const char* pos0
= pathCString
;
1452 const char* pos1
= pathCString
+1;
1453 for (kwsys_stl::string::size_type pos
= 0; *pos0
; ++ pos
)
1455 // make sure we don't convert an escaped space to a unix slash
1456 if ( *pos0
== '\\' && *pos1
!= ' ' )
1461 // Also, reuse the loop to check for slash followed by another slash
1462 if (*pos1
== '/' && *(pos1
+1) == '/' && !hasDoubleSlash
)
1465 // However, on windows if the first characters are both slashes,
1466 // then keep them that way, so that network paths can be handled.
1469 hasDoubleSlash
= true;
1472 hasDoubleSlash
= true;
1480 if ( hasDoubleSlash
)
1482 SystemTools::ReplaceString(path
, "//", "/");
1485 // remove any trailing slash
1488 // if there is a tilda ~ then replace it with HOME
1489 pathCString
= path
.c_str();
1490 if(pathCString
[0] == '~' && (pathCString
[1] == '/' || pathCString
[1] == '\0'))
1492 const char* homeEnv
= SystemTools::GetEnv("HOME");
1495 path
.replace(0,1,homeEnv
);
1498 #ifdef HAVE_GETPWNAM
1499 else if(pathCString
[0] == '~')
1501 kwsys_stl::string::size_type idx
= path
.find_first_of("/\0");
1502 kwsys_stl::string user
= path
.substr(1, idx
-1);
1503 passwd
* pw
= getpwnam(user
.c_str());
1506 path
.replace(0, idx
, pw
->pw_dir
);
1510 // remove trailing slash if the path is more than
1512 pathCString
= path
.c_str();
1513 if(path
.size() > 1 && *(pathCString
+(path
.size()-1)) == '/')
1515 // if it is c:/ then do not remove the trailing slash
1516 if(!((path
.size() == 3 && pathCString
[1] == ':')))
1518 path
= path
.substr(0, path
.size()-1);
1524 // change // to /, and escape any spaces in the path
1525 kwsys_stl::string
SystemTools::ConvertToUnixOutputPath(const char* path
)
1527 kwsys_stl::string ret
= path
;
1529 // remove // except at the beginning might be a cygwin drive
1530 kwsys_stl::string::size_type pos
=0;
1531 while((pos
= ret
.find("//", pos
)) != kwsys_stl::string::npos
)
1535 // escape spaces and () in the path
1536 if(ret
.find_first_of(" ") != kwsys_stl::string::npos
)
1538 kwsys_stl::string result
= "";
1540 for(const char* ch
= ret
.c_str(); *ch
!= '\0'; ++ch
)
1542 // if it is already escaped then don't try to escape it again
1543 if((*ch
== ' ') && lastch
!= '\\')
1555 kwsys_stl::string
SystemTools::ConvertToOutputPath(const char* path
)
1557 #if defined(_WIN32) && !defined(__CYGWIN__)
1558 return SystemTools::ConvertToWindowsOutputPath(path
);
1560 return SystemTools::ConvertToUnixOutputPath(path
);
1564 // remove double slashes not at the start
1565 kwsys_stl::string
SystemTools::ConvertToWindowsOutputPath(const char* path
)
1567 kwsys_stl::string ret
;
1568 // make it big enough for all of path and double quotes
1569 ret
.reserve(strlen(path
)+3);
1570 // put path into the string
1573 kwsys_stl::string::size_type pos
= 0;
1574 // first convert all of the slashes
1575 while((pos
= ret
.find('/', pos
)) != kwsys_stl::string::npos
)
1580 // check for really small paths
1585 // now clean up a bit and remove double slashes
1586 // Only if it is not the first position in the path which is a network
1588 pos
= 1; // start at position 1
1591 pos
= 2; // if the string is already quoted then start at 2
1597 while((pos
= ret
.find("\\\\", pos
)) != kwsys_stl::string::npos
)
1601 // now double quote the path if it has spaces in it
1602 // and is not already double quoted
1603 if(ret
.find(' ') != kwsys_stl::string::npos
1606 ret
.insert(static_cast<kwsys_stl::string::size_type
>(0),
1607 static_cast<kwsys_stl::string::size_type
>(1), '\"');
1608 ret
.append(1, '\"');
1613 bool SystemTools::CopyFileIfDifferent(const char* source
,
1614 const char* destination
)
1616 // special check for a destination that is a directory
1617 // FilesDiffer does not handle file to directory compare
1618 if(SystemTools::FileIsDirectory(destination
))
1620 kwsys_stl::string new_destination
= destination
;
1621 SystemTools::ConvertToUnixSlashes(new_destination
);
1622 new_destination
+= '/';
1623 kwsys_stl::string source_name
= source
;
1624 new_destination
+= SystemTools::GetFilenameName(source_name
);
1625 if(SystemTools::FilesDiffer(source
, new_destination
.c_str()))
1627 return SystemTools::CopyFileAlways(source
, destination
);
1631 // the files are the same so the copy is done return
1636 // source and destination are files so do a copy if they
1638 if(SystemTools::FilesDiffer(source
, destination
))
1640 return SystemTools::CopyFileAlways(source
, destination
);
1642 // at this point the files must be the same so return true
1646 #define KWSYS_ST_BUFFER 4096
1648 bool SystemTools::FilesDiffer(const char* source
,
1649 const char* destination
)
1651 struct stat statSource
;
1652 if (stat(source
, &statSource
) != 0)
1657 struct stat statDestination
;
1658 if (stat(destination
, &statDestination
) != 0)
1663 if(statSource
.st_size
!= statDestination
.st_size
)
1668 if(statSource
.st_size
== 0)
1673 #if defined(_WIN32) || defined(__CYGWIN__)
1674 kwsys_ios::ifstream
finSource(source
, (kwsys_ios::ios::binary
|
1675 kwsys_ios::ios::in
));
1676 kwsys_ios::ifstream
finDestination(destination
, (kwsys_ios::ios::binary
|
1677 kwsys_ios::ios::in
));
1679 kwsys_ios::ifstream
finSource(source
);
1680 kwsys_ios::ifstream
finDestination(destination
);
1682 if(!finSource
|| !finDestination
)
1687 // Compare the files a block at a time.
1688 char source_buf
[KWSYS_ST_BUFFER
];
1689 char dest_buf
[KWSYS_ST_BUFFER
];
1690 off_t nleft
= statSource
.st_size
;
1693 // Read a block from each file.
1694 kwsys_ios::streamsize nnext
= (nleft
> KWSYS_ST_BUFFER
)? KWSYS_ST_BUFFER
: static_cast<kwsys_ios::streamsize
>(nleft
);
1695 finSource
.read(source_buf
, nnext
);
1696 finDestination
.read(dest_buf
, nnext
);
1698 // If either failed to read assume they are different.
1699 if(static_cast<kwsys_ios::streamsize
>(finSource
.gcount()) != nnext
||
1700 static_cast<kwsys_ios::streamsize
>(finDestination
.gcount()) != nnext
)
1705 // If this block differs the file differs.
1706 if(memcmp(static_cast<const void*>(source_buf
),
1707 static_cast<const void*>(dest_buf
), nnext
) != 0)
1712 // Update the byte count remaining.
1716 // No differences found.
1722 * Copy a file named by "source" to the file named by "destination".
1724 bool SystemTools::CopyFileAlways(const char* source
, const char* destination
)
1726 // If files are the same do not copy
1727 if ( SystemTools::SameFile(source
, destination
) )
1732 bool perms
= SystemTools::GetPermissions(source
, perm
);
1734 const int bufferSize
= 4096;
1735 char buffer
[bufferSize
];
1737 // If destination is a directory, try to create a file with the same
1738 // name as the source in that directory.
1740 kwsys_stl::string new_destination
;
1741 if(SystemTools::FileExists(destination
) &&
1742 SystemTools::FileIsDirectory(destination
))
1744 new_destination
= destination
;
1745 SystemTools::ConvertToUnixSlashes(new_destination
);
1746 new_destination
+= '/';
1747 kwsys_stl::string source_name
= source
;
1748 new_destination
+= SystemTools::GetFilenameName(source_name
);
1749 destination
= new_destination
.c_str();
1752 // Create destination directory
1754 kwsys_stl::string destination_dir
= destination
;
1755 destination_dir
= SystemTools::GetFilenamePath(destination_dir
);
1756 SystemTools::MakeDirectory(destination_dir
.c_str());
1760 #if defined(_WIN32) || defined(__CYGWIN__)
1761 kwsys_ios::ifstream
fin(source
,
1762 kwsys_ios::ios::binary
| kwsys_ios::ios::in
);
1764 kwsys_ios::ifstream
fin(source
);
1771 // try and remove the destination file so that read only destination files
1772 // can be written to.
1773 // If the remove fails continue so that files in read only directories
1774 // that do not allow file removal can be modified.
1775 SystemTools::RemoveFile(destination
);
1777 #if defined(_WIN32) || defined(__CYGWIN__)
1778 kwsys_ios::ofstream
fout(destination
,
1779 kwsys_ios::ios::binary
| kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1781 kwsys_ios::ofstream
fout(destination
,
1782 kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1789 // This copy loop is very sensitive on certain platforms with
1790 // slightly broken stream libraries (like HPUX). Normally, it is
1791 // incorrect to not check the error condition on the fin.read()
1792 // before using the data, but the fin.gcount() will be zero if an
1793 // error occurred. Therefore, the loop should be safe everywhere.
1796 fin
.read(buffer
, bufferSize
);
1799 fout
.write(buffer
, fin
.gcount());
1803 // Make sure the operating system has finished writing the file
1804 // before closing it. This will ensure the file is finished before
1812 struct stat statSource
, statDestination
;
1813 statSource
.st_size
= 12345;
1814 statDestination
.st_size
= 12345;
1815 if(stat(source
, &statSource
) != 0)
1819 else if(stat(destination
, &statDestination
) != 0)
1823 else if(statSource
.st_size
!= statDestination
.st_size
)
1829 if ( !SystemTools::SetPermissions(destination
, perm
) )
1837 //----------------------------------------------------------------------------
1838 bool SystemTools::CopyAFile(const char* source
, const char* destination
,
1843 return SystemTools::CopyFileAlways(source
, destination
);
1847 return SystemTools::CopyFileIfDifferent(source
, destination
);
1852 * Copy a directory content from "source" directory to the directory named by
1855 bool SystemTools::CopyADirectory(const char* source
, const char* destination
,
1861 if ( !SystemTools::MakeDirectory(destination
) )
1865 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
1867 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
1868 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
1870 kwsys_stl::string fullPath
= source
;
1872 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1873 if(SystemTools::FileIsDirectory(fullPath
.c_str()))
1875 kwsys_stl::string fullDestPath
= destination
;
1876 fullDestPath
+= "/";
1877 fullDestPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1878 if (!SystemTools::CopyADirectory(fullPath
.c_str(),
1879 fullDestPath
.c_str(),
1887 if(!SystemTools::CopyAFile(fullPath
.c_str(), destination
, always
))
1899 // return size of file; also returns zero if no file exists
1900 unsigned long SystemTools::FileLength(const char* filename
)
1903 if (stat(filename
, &fs
) != 0)
1909 return static_cast<unsigned long>(fs
.st_size
);
1913 int SystemTools::Strucmp(const char *s1
, const char *s2
)
1915 // lifted from Graphvis http://www.graphviz.org
1916 while ((*s1
!= '\0')
1917 && (tolower(*s1
) == tolower(*s2
)))
1923 return tolower(*s1
) - tolower(*s2
);
1926 // return file's modified time
1927 long int SystemTools::ModifiedTime(const char* filename
)
1930 if (stat(filename
, &fs
) != 0)
1936 return static_cast<long int>(fs
.st_mtime
);
1940 // return file's creation time
1941 long int SystemTools::CreationTime(const char* filename
)
1944 if (stat(filename
, &fs
) != 0)
1950 return fs
.st_ctime
>= 0 ? static_cast<long int>(fs
.st_ctime
) : 0;
1954 bool SystemTools::ConvertDateMacroString(const char *str
, time_t *tmt
)
1956 if (!str
|| !tmt
|| strlen(str
) > 11)
1964 // The compilation date of the current source file. The date is a string
1965 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
1966 // dates generated by the library function asctime declared in TIME.H.
1968 // index: 012345678901
1969 // format: Mmm dd yyyy
1970 // example: Dec 19 2003
1972 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1975 strcpy(buffer
, str
);
1978 char *ptr
= strstr(month_names
, buffer
);
1984 int month
= (ptr
- month_names
) / 3;
1985 int day
= atoi(buffer
+ 4);
1986 int year
= atoi(buffer
+ 7);
1995 tmt2
.tm_mon
= month
;
1996 tmt2
.tm_year
= year
- 1900;
1998 *tmt
= mktime(&tmt2
);
2002 bool SystemTools::ConvertTimeStampMacroString(const char *str
, time_t *tmt
)
2004 if (!str
|| !tmt
|| strlen(str
) > 26)
2012 // The date and time of the last modification of the current source file,
2013 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
2014 /// where Ddd is the abbreviated day of the week and Date is an integer
2017 // index: 0123456789
2020 // format: Ddd Mmm Date hh:mm:ss yyyy
2021 // example: Fri Dec 19 14:34:58 2003
2023 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
2026 strcpy(buffer
, str
);
2029 char *ptr
= strstr(month_names
, buffer
+ 4);
2035 int month
= (ptr
- month_names
) / 3;
2036 int day
= atoi(buffer
+ 8);
2037 int hour
= atoi(buffer
+ 11);
2038 int min
= atoi(buffer
+ 14);
2039 int sec
= atoi(buffer
+ 17);
2040 int year
= atoi(buffer
+ 20);
2043 tmt2
.tm_hour
= hour
;
2049 tmt2
.tm_mon
= month
;
2050 tmt2
.tm_year
= year
- 1900;
2052 *tmt
= mktime(&tmt2
);
2056 kwsys_stl::string
SystemTools::GetLastSystemError()
2062 bool SystemTools::RemoveFile(const char* source
)
2066 if ( !SystemTools::GetPermissions(source
, mode
) )
2070 /* Win32 unlink is stupid --- it fails if the file is read-only */
2071 SystemTools::SetPermissions(source
, S_IWRITE
);
2073 bool res
= unlink(source
) != 0 ? false : true;
2077 SystemTools::SetPermissions(source
, mode
);
2083 bool SystemTools::RemoveADirectory(const char* source
)
2088 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
2090 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
2091 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
2093 kwsys_stl::string fullPath
= source
;
2095 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
2096 if(SystemTools::FileIsDirectory(fullPath
.c_str()) &&
2097 !SystemTools::FileIsSymlink(fullPath
.c_str()))
2099 if (!SystemTools::RemoveADirectory(fullPath
.c_str()))
2106 if(!SystemTools::RemoveFile(fullPath
.c_str()))
2114 return (Rmdir(source
) == 0);
2119 size_t SystemTools::GetMaximumFilePathLength()
2121 return KWSYS_SYSTEMTOOLS_MAXPATH
;
2125 * Find the file the given name. Searches the given path and then
2126 * the system search path. Returns the full path to the file if it is
2127 * found. Otherwise, the empty string is returned.
2129 kwsys_stl::string SystemTools
2130 ::FindName(const char* name
,
2131 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2132 bool no_system_path
)
2134 // Add the system search path to our path first
2135 kwsys_stl::vector
<kwsys_stl::string
> path
;
2136 if (!no_system_path
)
2138 SystemTools::GetPath(path
, "CMAKE_FILE_PATH");
2139 SystemTools::GetPath(path
);
2141 // now add the additional paths
2143 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= userPaths
.begin();
2144 i
!= userPaths
.end(); ++i
)
2149 // Add a trailing slash to all paths to aid the search process.
2151 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
2152 i
!= path
.end(); ++i
)
2154 kwsys_stl::string
& p
= *i
;
2155 if(p
.empty() || p
[p
.size()-1] != '/')
2161 // now look for the file
2162 kwsys_stl::string tryPath
;
2163 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
2164 p
!= path
.end(); ++p
)
2168 if(SystemTools::FileExists(tryPath
.c_str()))
2173 // Couldn't find the file.
2178 * Find the file the given name. Searches the given path and then
2179 * the system search path. Returns the full path to the file if it is
2180 * found. Otherwise, the empty string is returned.
2182 kwsys_stl::string SystemTools
2183 ::FindFile(const char* name
,
2184 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2185 bool no_system_path
)
2187 kwsys_stl::string tryPath
= SystemTools::FindName(name
, userPaths
, no_system_path
);
2188 if(tryPath
!= "" && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2190 return SystemTools::CollapseFullPath(tryPath
.c_str());
2192 // Couldn't find the file.
2197 * Find the directory the given name. Searches the given path and then
2198 * the system search path. Returns the full path to the directory if it is
2199 * found. Otherwise, the empty string is returned.
2201 kwsys_stl::string SystemTools
2202 ::FindDirectory(const char* name
,
2203 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2204 bool no_system_path
)
2206 kwsys_stl::string tryPath
= SystemTools::FindName(name
, userPaths
, no_system_path
);
2207 if(tryPath
!= "" && SystemTools::FileIsDirectory(tryPath
.c_str()))
2209 return SystemTools::CollapseFullPath(tryPath
.c_str());
2211 // Couldn't find the file.
2216 * Find the executable with the given name. Searches the given path and then
2217 * the system search path. Returns the full path to the executable if it is
2218 * found. Otherwise, the empty string is returned.
2220 kwsys_stl::string
SystemTools::FindProgram(
2222 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2223 bool no_system_path
)
2225 if(!nameIn
|| !*nameIn
)
2229 kwsys_stl::string name
= nameIn
;
2230 kwsys_stl::vector
<kwsys_stl::string
> extensions
;
2231 #if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
2232 bool hasExtension
= false;
2233 // check to see if the name already has a .xxx at
2235 if(name
.size() > 3 && name
[name
.size()-4] == '.')
2237 hasExtension
= true;
2239 // on windows try .com then .exe
2242 extensions
.push_back(".com");
2243 extensions
.push_back(".exe");
2246 kwsys_stl::string tryPath
;
2248 // first try with extensions if the os supports them
2249 if(extensions
.size())
2251 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
=
2252 extensions
.begin(); i
!= extensions
.end(); ++i
)
2256 if(SystemTools::FileExists(tryPath
.c_str()) &&
2257 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2259 return SystemTools::CollapseFullPath(tryPath
.c_str());
2263 // now try just the name
2265 if(SystemTools::FileExists(tryPath
.c_str()) &&
2266 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2268 return SystemTools::CollapseFullPath(tryPath
.c_str());
2270 // now construct the path
2271 kwsys_stl::vector
<kwsys_stl::string
> path
;
2272 // Add the system search path to our path.
2273 if (!no_system_path
)
2275 SystemTools::GetPath(path
);
2277 // now add the additional paths
2279 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
=
2280 userPaths
.begin(); i
!= userPaths
.end(); ++i
)
2285 // Add a trailing slash to all paths to aid the search process.
2287 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
2288 i
!= path
.end(); ++i
)
2290 kwsys_stl::string
& p
= *i
;
2291 if(p
.empty() || p
[p
.size()-1] != '/')
2298 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator p
= path
.begin();
2299 p
!= path
.end(); ++p
)
2302 // Remove double quotes from the path on windows
2303 SystemTools::ReplaceString(*p
, "\"", "");
2305 // first try with extensions
2306 if(extensions
.size())
2308 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator ext
2309 = extensions
.begin(); ext
!= extensions
.end(); ++ext
)
2314 if(SystemTools::FileExists(tryPath
.c_str()) &&
2315 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2317 return SystemTools::CollapseFullPath(tryPath
.c_str());
2321 // now try it without them
2324 if(SystemTools::FileExists(tryPath
.c_str()) &&
2325 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2327 return SystemTools::CollapseFullPath(tryPath
.c_str());
2330 // Couldn't find the program.
2334 kwsys_stl::string
SystemTools::FindProgram(
2335 const kwsys_stl::vector
<kwsys_stl::string
>& names
,
2336 const kwsys_stl::vector
<kwsys_stl::string
>& path
,
2339 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator it
= names
.begin();
2340 it
!= names
.end() ; ++it
)
2342 // Try to find the program.
2343 kwsys_stl::string result
= SystemTools::FindProgram(it
->c_str(),
2346 if ( !result
.empty() )
2355 * Find the library with the given name. Searches the given path and then
2356 * the system search path. Returns the full path to the library if it is
2357 * found. Otherwise, the empty string is returned.
2359 kwsys_stl::string SystemTools
2360 ::FindLibrary(const char* name
,
2361 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
)
2363 // See if the executable exists as written.
2364 if(SystemTools::FileExists(name
) &&
2365 !SystemTools::FileIsDirectory(name
))
2367 return SystemTools::CollapseFullPath(name
);
2370 // Add the system search path to our path.
2371 kwsys_stl::vector
<kwsys_stl::string
> path
;
2372 SystemTools::GetPath(path
);
2373 // now add the additional paths
2375 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= userPaths
.begin();
2376 i
!= userPaths
.end(); ++i
)
2381 // Add a trailing slash to all paths to aid the search process.
2383 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
2384 i
!= path
.end(); ++i
)
2386 kwsys_stl::string
& p
= *i
;
2387 if(p
.empty() || p
[p
.size()-1] != '/')
2393 kwsys_stl::string tryPath
;
2394 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
2395 p
!= path
.end(); ++p
)
2397 #if defined(__APPLE__)
2400 tryPath
+= ".framework";
2401 if(SystemTools::FileExists(tryPath
.c_str())
2402 && SystemTools::FileIsDirectory(tryPath
.c_str()))
2404 return SystemTools::CollapseFullPath(tryPath
.c_str());
2407 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
2411 if(SystemTools::FileExists(tryPath
.c_str())
2412 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2414 return SystemTools::CollapseFullPath(tryPath
.c_str());
2421 if(SystemTools::FileExists(tryPath
.c_str())
2422 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2424 return SystemTools::CollapseFullPath(tryPath
.c_str());
2430 if(SystemTools::FileExists(tryPath
.c_str())
2431 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2433 return SystemTools::CollapseFullPath(tryPath
.c_str());
2439 if(SystemTools::FileExists(tryPath
.c_str())
2440 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2442 return SystemTools::CollapseFullPath(tryPath
.c_str());
2447 tryPath
+= ".dylib";
2448 if(SystemTools::FileExists(tryPath
.c_str())
2449 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2451 return SystemTools::CollapseFullPath(tryPath
.c_str());
2457 if(SystemTools::FileExists(tryPath
.c_str())
2458 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2460 return SystemTools::CollapseFullPath(tryPath
.c_str());
2465 // Couldn't find the library.
2469 kwsys_stl::string
SystemTools::GetRealPath(const char* path
)
2471 kwsys_stl::string ret
;
2472 Realpath(path
, ret
);
2476 bool SystemTools::FileIsDirectory(const char* name
)
2478 // Remove any trailing slash from the name.
2479 char buffer
[KWSYS_SYSTEMTOOLS_MAXPATH
];
2480 int last
= static_cast<int>(strlen(name
))-1;
2481 if(last
> 0 && (name
[last
] == '/' || name
[last
] == '\\')
2482 && strcmp(name
, "/") !=0)
2484 memcpy(buffer
, name
, last
);
2489 // Now check the file node type.
2491 if(stat(name
, &fs
) == 0)
2493 #if defined( _WIN32 )
2494 return ((fs
.st_mode
& _S_IFDIR
) != 0);
2496 return S_ISDIR(fs
.st_mode
);
2505 bool SystemTools::FileIsSymlink(const char* name
)
2507 #if defined( _WIN32 )
2512 if(lstat(name
, &fs
) == 0)
2514 return S_ISLNK(fs
.st_mode
);
2523 #if defined(_WIN32) && !defined(__CYGWIN__)
2524 bool SystemTools::CreateSymlink(const char*, const char*)
2529 bool SystemTools::CreateSymlink(const char* origName
, const char* newName
)
2531 return symlink(origName
, newName
) >= 0;
2535 #if defined(_WIN32) && !defined(__CYGWIN__)
2536 bool SystemTools::ReadSymlink(const char*, kwsys_stl::string
&)
2541 bool SystemTools::ReadSymlink(const char* newName
,
2542 kwsys_stl::string
& origName
)
2544 char buf
[KWSYS_SYSTEMTOOLS_MAXPATH
+1];
2546 static_cast<int>(readlink(newName
, buf
, KWSYS_SYSTEMTOOLS_MAXPATH
));
2549 // Add null-terminator.
2561 int SystemTools::ChangeDirectory(const char *dir
)
2566 kwsys_stl::string
SystemTools::GetCurrentWorkingDirectory(bool collapse
)
2569 const char* cwd
= Getcwd(buf
, 2048);
2570 kwsys_stl::string path
;
2577 return SystemTools::CollapseFullPath(path
.c_str());
2582 kwsys_stl::string
SystemTools::GetProgramPath(const char* in_name
)
2584 kwsys_stl::string dir
, file
;
2585 SystemTools::SplitProgramPath(in_name
, dir
, file
);
2589 bool SystemTools::SplitProgramPath(const char* in_name
,
2590 kwsys_stl::string
& dir
,
2591 kwsys_stl::string
& file
,
2596 SystemTools::ConvertToUnixSlashes(dir
);
2598 if(!SystemTools::FileIsDirectory(dir
.c_str()))
2600 kwsys_stl::string::size_type slashPos
= dir
.rfind("/");
2601 if(slashPos
!= kwsys_stl::string::npos
)
2603 file
= dir
.substr(slashPos
+1);
2604 dir
= dir
.substr(0, slashPos
);
2612 if(!(dir
== "") && !SystemTools::FileIsDirectory(dir
.c_str()))
2614 kwsys_stl::string oldDir
= in_name
;
2615 SystemTools::ConvertToUnixSlashes(oldDir
);
2622 bool SystemTools::FindProgramPath(const char* argv0
,
2623 kwsys_stl::string
& pathOut
,
2624 kwsys_stl::string
& errorMsg
,
2625 const char* exeName
,
2626 const char* buildDir
,
2627 const char* installPrefix
)
2629 kwsys_stl::vector
<kwsys_stl::string
> failures
;
2630 kwsys_stl::string self
= argv0
? argv0
: "";
2631 failures
.push_back(self
);
2632 SystemTools::ConvertToUnixSlashes(self
);
2633 self
= SystemTools::FindProgram(self
.c_str());
2634 if(!SystemTools::FileExists(self
.c_str()))
2638 kwsys_stl::string intdir
= ".";
2640 intdir
= CMAKE_INTDIR
;
2647 self
+= SystemTools::GetExecutableExtension();
2652 if(!SystemTools::FileExists(self
.c_str()))
2654 failures
.push_back(self
);
2655 self
= installPrefix
;
2660 if(!SystemTools::FileExists(self
.c_str()))
2662 failures
.push_back(self
);
2663 kwsys_ios::ostringstream msg
;
2664 msg
<< "Can not find the command line program ";
2672 msg
<< " argv[0] = \"" << argv0
<< "\"\n";
2674 msg
<< " Attempted paths:\n";
2675 kwsys_stl::vector
<kwsys_stl::string
>::iterator i
;
2676 for(i
=failures
.begin(); i
!= failures
.end(); ++i
)
2678 msg
<< " \"" << i
->c_str() << "\"\n";
2680 errorMsg
= msg
.str();
2688 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_relative
)
2690 return SystemTools::CollapseFullPath(in_relative
, 0);
2693 void SystemTools::AddTranslationPath(const char * a
, const char * b
)
2695 kwsys_stl::string path_a
= a
;
2696 kwsys_stl::string path_b
= b
;
2697 SystemTools::ConvertToUnixSlashes(path_a
);
2698 SystemTools::ConvertToUnixSlashes(path_b
);
2699 // First check this is a directory path, since we don't want the table to
2701 if( SystemTools::FileIsDirectory( path_a
.c_str() ) )
2703 // Make sure the path is a full path and does not contain no '..'
2704 // Ken--the following code is incorrect. .. can be in a valid path
2705 // for example /home/martink/MyHubba...Hubba/Src
2706 if( SystemTools::FileIsFullPath(path_b
.c_str()) && path_b
.find("..")
2707 == kwsys_stl::string::npos
)
2709 // Before inserting make sure path ends with '/'
2710 if(path_a
.size() && path_a
[path_a
.size() -1] != '/')
2714 if(path_b
.size() && path_b
[path_b
.size() -1] != '/')
2718 if( !(path_a
== path_b
) )
2720 SystemTools::TranslationMap
->insert(
2721 SystemToolsTranslationMap::value_type(path_a
, path_b
));
2727 void SystemTools::AddKeepPath(const char* dir
)
2729 kwsys_stl::string cdir
;
2730 Realpath(SystemTools::CollapseFullPath(dir
).c_str(), cdir
);
2731 SystemTools::AddTranslationPath(cdir
.c_str(), dir
);
2734 void SystemTools::CheckTranslationPath(kwsys_stl::string
& path
)
2736 // Do not translate paths that are too short to have meaningful
2743 // Always add a trailing slash before translation. It does not
2744 // matter if this adds an extra slash, but we do not want to
2745 // translate part of a directory (like the foo part of foo-dir).
2748 // In case a file was specified we still have to go through this:
2749 // Now convert any path found in the table back to the one desired:
2750 kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>::const_iterator it
;
2751 for(it
= SystemTools::TranslationMap
->begin();
2752 it
!= SystemTools::TranslationMap
->end();
2755 // We need to check of the path is a substring of the other path
2756 if(path
.find( it
->first
) == 0)
2758 path
= path
.replace( 0, it
->first
.size(), it
->second
);
2762 // Remove the trailing slash we added before.
2763 path
.erase(path
.end()-1, path
.end());
2767 SystemToolsAppendComponents(
2768 kwsys_stl::vector
<kwsys_stl::string
>& out_components
,
2769 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator first
,
2770 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator last
)
2772 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= first
;
2777 if(out_components
.begin() != out_components
.end())
2779 out_components
.erase(out_components
.end()-1, out_components
.end());
2782 else if(!(*i
== ".") && !(*i
== ""))
2784 out_components
.push_back(*i
);
2789 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_path
,
2790 const char* in_base
)
2792 // Collect the output path components.
2793 kwsys_stl::vector
<kwsys_stl::string
> out_components
;
2795 // Split the input path components.
2796 kwsys_stl::vector
<kwsys_stl::string
> path_components
;
2797 SystemTools::SplitPath(in_path
, path_components
);
2799 // If the input path is relative, start with a base path.
2800 if(path_components
[0].length() == 0)
2802 kwsys_stl::vector
<kwsys_stl::string
> base_components
;
2805 // Use the given base path.
2806 SystemTools::SplitPath(in_base
, base_components
);
2810 // Use the current working directory as a base path.
2812 if(const char* cwd
= Getcwd(buf
, 2048))
2814 SystemTools::SplitPath(cwd
, base_components
);
2822 // Append base path components to the output path.
2823 out_components
.push_back(base_components
[0]);
2824 SystemToolsAppendComponents(out_components
,
2825 base_components
.begin()+1,
2826 base_components
.end());
2829 // Append input path components to the output path.
2830 SystemToolsAppendComponents(out_components
,
2831 path_components
.begin(),
2832 path_components
.end());
2834 // Transform the path back to a string.
2835 kwsys_stl::string newPath
= SystemTools::JoinPath(out_components
);
2837 // Update the translation table with this potentially new path. I am not
2838 // sure why this line is here, it seems really questionable, but yet I
2839 // would put good money that if I remove it something will break, basically
2840 // from what I can see it created a mapping from the collapsed path, to be
2841 // replaced by the input path, which almost completely does the opposite of
2842 // this function, the only thing preventing this from happening a lot is
2843 // that if the in_path has a .. in it, then it is not added to the
2844 // translation table. So for most calls this either does nothing due to the
2845 // .. or it adds a translation between identical paths as nothing was
2846 // collapsed, so I am going to try to comment it out, and see what hits the
2847 // fan, hopefully quickly.
2848 // Commented out line below:
2849 //SystemTools::AddTranslationPath(newPath.c_str(), in_path);
2851 SystemTools::CheckTranslationPath(newPath
);
2853 newPath
= SystemTools::GetActualCaseForPath(newPath
.c_str());
2854 SystemTools::ConvertToUnixSlashes(newPath
);
2856 // Return the reconstructed path.
2860 // compute the relative path from here to there
2861 kwsys_stl::string
SystemTools::RelativePath(const char* local
, const char* remote
)
2863 if(!SystemTools::FileIsFullPath(local
))
2867 if(!SystemTools::FileIsFullPath(remote
))
2872 // split up both paths into arrays of strings using / as a separator
2873 kwsys_stl::vector
<kwsys::String
> localSplit
= SystemTools::SplitString(local
, '/', true);
2874 kwsys_stl::vector
<kwsys::String
> remoteSplit
= SystemTools::SplitString(remote
, '/', true);
2875 kwsys_stl::vector
<kwsys::String
> commonPath
; // store shared parts of path in this array
2876 kwsys_stl::vector
<kwsys::String
> finalPath
; // store the final relative path here
2877 // count up how many matching directory names there are from the start
2878 unsigned int sameCount
= 0;
2880 ((sameCount
<= (localSplit
.size()-1)) && (sameCount
<= (remoteSplit
.size()-1)))
2882 // for windows and apple do a case insensitive string compare
2883 #if defined(_WIN32) || defined(__APPLE__)
2884 SystemTools::Strucmp(localSplit
[sameCount
].c_str(),
2885 remoteSplit
[sameCount
].c_str()) == 0
2887 localSplit
[sameCount
] == remoteSplit
[sameCount
]
2891 // put the common parts of the path into the commonPath array
2892 commonPath
.push_back(localSplit
[sameCount
]);
2893 // erase the common parts of the path from the original path arrays
2894 localSplit
[sameCount
] = "";
2895 remoteSplit
[sameCount
] = "";
2899 // If there is nothing in common at all then just return the full
2900 // path. This is the case only on windows when the paths have
2901 // different drive letters. On unix two full paths always at least
2902 // have the root "/" in common so we will return a relative path
2903 // that passes through the root directory.
2909 // for each entry that is not common in the local path
2910 // add a ../ to the finalpath array, this gets us out of the local
2911 // path into the remote dir
2912 for(unsigned int i
= 0; i
< localSplit
.size(); ++i
)
2914 if(localSplit
[i
].size())
2916 finalPath
.push_back("../");
2919 // for each entry that is not common in the remote path add it
2920 // to the final path.
2921 for(kwsys_stl::vector
<String
>::iterator vit
= remoteSplit
.begin();
2922 vit
!= remoteSplit
.end(); ++vit
)
2926 finalPath
.push_back(*vit
);
2929 kwsys_stl::string relativePath
; // result string
2930 // now turn the array of directories into a unix path by puttint /
2931 // between each entry that does not already have one
2932 for(kwsys_stl::vector
<String
>::iterator vit1
= finalPath
.begin();
2933 vit1
!= finalPath
.end(); ++vit1
)
2935 if(relativePath
.size() && relativePath
[relativePath
.size()-1] != '/')
2937 relativePath
+= "/";
2939 relativePath
+= *vit1
;
2941 return relativePath
;
2944 // OK, some fun stuff to get the actual case of a given path.
2945 // Basically, you just need to call ShortPath, then GetLongPathName,
2946 // However, GetLongPathName is not implemented on windows NT and 95,
2947 // so we have to simulate it on those versions
2949 int OldWindowsGetLongPath(kwsys_stl::string
const& shortPath
,
2950 kwsys_stl::string
& longPath
)
2952 kwsys_stl::string::size_type iFound
= shortPath
.rfind('/');
2953 if (iFound
> 1 && iFound
!= shortPath
.npos
)
2955 // recurse to peel off components
2957 if (OldWindowsGetLongPath(shortPath
.substr(0, iFound
), longPath
) > 0)
2960 if (shortPath
[1] != '/')
2962 WIN32_FIND_DATA findData
;
2964 // append the long component name to the path
2966 if (INVALID_HANDLE_VALUE
!= ::FindFirstFile
2967 (shortPath
.c_str(), &findData
))
2969 longPath
+= findData
.cFileName
;
2973 // if FindFirstFile fails, return the error code
2983 longPath
= shortPath
;
2985 return (int)longPath
.size();
2989 int PortableGetLongPathName(const char* pathIn
,
2990 kwsys_stl::string
& longPath
)
2992 HMODULE lh
= LoadLibrary("Kernel32.dll");
2995 FARPROC proc
= GetProcAddress(lh
, "GetLongPathNameA");
2998 typedef DWORD (WINAPI
* GetLongFunctionPtr
) (LPCSTR
,LPSTR
,DWORD
);
2999 GetLongFunctionPtr func
= (GetLongFunctionPtr
)proc
;
3000 char buffer
[MAX_PATH
+1];
3001 int len
= (*func
)(pathIn
, buffer
, MAX_PATH
+1);
3002 if(len
== 0 || len
> MAX_PATH
+1)
3013 return OldWindowsGetLongPath(pathIn
, longPath
);
3018 //----------------------------------------------------------------------------
3019 kwsys_stl::string
SystemTools::GetActualCaseForPath(const char* p
)
3024 // Check to see if actual case has already been called
3025 // for this path, and the result is stored in the LongPathMap
3026 SystemToolsTranslationMap::iterator i
=
3027 SystemTools::LongPathMap
->find(p
);
3028 if(i
!= SystemTools::LongPathMap
->end())
3032 kwsys_stl::string shortPath
;
3033 if(!SystemTools::GetShortPath(p
, shortPath
))
3037 kwsys_stl::string longPath
;
3038 int len
= PortableGetLongPathName(shortPath
.c_str(), longPath
);
3039 if(len
== 0 || len
> MAX_PATH
+1)
3043 // make sure drive letter is always upper case
3044 if(longPath
.size() > 1 && longPath
[1] == ':')
3046 longPath
[0] = toupper(longPath
[0]);
3048 (*SystemTools::LongPathMap
)[p
] = longPath
;
3053 //----------------------------------------------------------------------------
3054 const char* SystemTools::SplitPathRootComponent(const char* p
,
3055 kwsys_stl::string
* root
)
3057 // Identify the root component.
3059 if((c
[0] == '/' && c
[1] == '/') || (c
[0] == '\\' && c
[1] == '\\'))
3068 else if(c
[0] == '/')
3077 else if(c
[0] && c
[1] == ':' && (c
[2] == '/' || c
[2] == '\\'))
3087 else if(c
[0] && c
[1] == ':')
3089 // Path relative to a windows drive working directory.
3097 else if(c
[0] == '~')
3099 // Home directory. The returned root should always have a
3100 // trailing slash so that appending components as
3101 // c[0]c[1]/c[2]/... works. The remaining path returned should
3102 // skip the first slash if it exists:
3104 // "~" : root = "~/" , return ""
3105 // "~/ : root = "~/" , return ""
3106 // "~/x : root = "~/" , return "x"
3107 // "~u" : root = "~u/", return ""
3108 // "~u/" : root = "~u/", return ""
3109 // "~u/x" : root = "~u/", return "x"
3111 while(c
[n
] && c
[n
] != '/')
3135 // Return the remaining path.
3139 //----------------------------------------------------------------------------
3140 void SystemTools::SplitPath(const char* p
,
3141 kwsys_stl::vector
<kwsys_stl::string
>& components
,
3142 bool expand_home_dir
)
3147 // Identify the root component.
3149 kwsys_stl::string root
;
3150 c
= SystemTools::SplitPathRootComponent(c
, &root
);
3152 // Expand home directory references if requested.
3153 if(expand_home_dir
&& !root
.empty() && root
[0] == '~')
3155 kwsys_stl::string homedir
;
3156 root
= root
.substr(0, root
.size()-1);
3157 if(root
.size() == 1)
3159 #if defined(_WIN32) && !defined(__CYGWIN__)
3160 if(const char* userp
= getenv("USERPROFILE"))
3166 if(const char* h
= getenv("HOME"))
3171 #ifdef HAVE_GETPWNAM
3172 else if(passwd
* pw
= getpwnam(root
.c_str()+1))
3176 homedir
= pw
->pw_dir
;
3180 if(!homedir
.empty() && (homedir
[homedir
.size()-1] == '/' ||
3181 homedir
[homedir
.size()-1] == '\\'))
3183 homedir
= homedir
.substr(0, homedir
.size()-1);
3185 SystemTools::SplitPath(homedir
.c_str(), components
);
3189 components
.push_back(root
);
3193 // Parse the remaining components.
3194 const char* first
= c
;
3195 const char* last
= first
;
3198 if(*last
== '/' || *last
== '\\')
3200 // End of a component. Save it.
3201 components
.push_back(kwsys_stl::string(first
, last
-first
));
3206 // Save the last component unless there were no components.
3209 components
.push_back(kwsys_stl::string(first
, last
-first
));
3213 //----------------------------------------------------------------------------
3215 SystemTools::JoinPath(const kwsys_stl::vector
<kwsys_stl::string
>& components
)
3217 return SystemTools::JoinPath(components
.begin(), components
.end());
3220 //----------------------------------------------------------------------------
3223 ::JoinPath(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator first
,
3224 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator last
)
3226 // Construct result in a single string.
3227 kwsys_stl::string result
;
3229 // The first two components do not add a slash.
3239 // All remaining components are always separated with a slash.
3240 while(first
!= last
)
3246 // Return the concatenated result.
3250 //----------------------------------------------------------------------------
3251 bool SystemTools::ComparePath(const char* c1
, const char* c2
)
3253 #if defined(_WIN32) || defined(__APPLE__)
3255 return _stricmp(c1
, c2
) == 0;
3256 # elif defined(__APPLE__) || defined(__GNUC__)
3257 return strcasecmp(c1
, c2
) == 0;
3259 return SystemTools::Strucmp(c1
, c2
) == 0;
3262 return strcmp(c1
, c2
) == 0;
3266 //----------------------------------------------------------------------------
3267 bool SystemTools::Split(const char* str
, kwsys_stl::vector
<kwsys_stl::string
>& lines
, char separator
)
3269 kwsys_stl::string
data(str
);
3270 kwsys_stl::string::size_type lpos
= 0;
3271 while(lpos
< data
.length())
3273 kwsys_stl::string::size_type rpos
= data
.find_first_of(separator
, lpos
);
3274 if(rpos
== kwsys_stl::string::npos
)
3276 // Line ends at end of string without a newline.
3277 lines
.push_back(data
.substr(lpos
));
3282 // Line ends in a "\n", remove the character.
3283 lines
.push_back(data
.substr(lpos
, rpos
-lpos
));
3290 //----------------------------------------------------------------------------
3291 bool SystemTools::Split(const char* str
, kwsys_stl::vector
<kwsys_stl::string
>& lines
)
3293 kwsys_stl::string
data(str
);
3294 kwsys_stl::string::size_type lpos
= 0;
3295 while(lpos
< data
.length())
3297 kwsys_stl::string::size_type rpos
= data
.find_first_of("\n", lpos
);
3298 if(rpos
== kwsys_stl::string::npos
)
3300 // Line ends at end of string without a newline.
3301 lines
.push_back(data
.substr(lpos
));
3304 if((rpos
> lpos
) && (data
[rpos
-1] == '\r'))
3306 // Line ends in a "\r\n" pair, remove both characters.
3307 lines
.push_back(data
.substr(lpos
, (rpos
-1)-lpos
));
3311 // Line ends in a "\n", remove the character.
3312 lines
.push_back(data
.substr(lpos
, rpos
-lpos
));
3320 * Return path of a full filename (no trailing slashes).
3321 * Warning: returned path is converted to Unix slashes format.
3323 kwsys_stl::string
SystemTools::GetFilenamePath(const kwsys_stl::string
& filename
)
3325 kwsys_stl::string fn
= filename
;
3326 SystemTools::ConvertToUnixSlashes(fn
);
3328 kwsys_stl::string::size_type slash_pos
= fn
.rfind("/");
3329 if(slash_pos
!= kwsys_stl::string::npos
)
3331 kwsys_stl::string ret
= fn
.substr(0, slash_pos
);
3332 if(ret
.size() == 2 && ret
[1] == ':')
3350 * Return file name of a full filename (i.e. file name without path).
3352 kwsys_stl::string
SystemTools::GetFilenameName(const kwsys_stl::string
& filename
)
3355 kwsys_stl::string::size_type slash_pos
= filename
.find_last_of("/\\");
3357 kwsys_stl::string::size_type slash_pos
= filename
.find_last_of("/");
3359 if(slash_pos
!= kwsys_stl::string::npos
)
3361 return filename
.substr(slash_pos
+ 1);
3371 * Return file extension of a full filename (dot included).
3372 * Warning: this is the longest extension (for example: .tar.gz)
3374 kwsys_stl::string
SystemTools::GetFilenameExtension(const kwsys_stl::string
& filename
)
3376 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3377 kwsys_stl::string::size_type dot_pos
= name
.find(".");
3378 if(dot_pos
!= kwsys_stl::string::npos
)
3380 return name
.substr(dot_pos
);
3389 * Return file extension of a full filename (dot included).
3390 * Warning: this is the shortest extension (for example: .gz of .tar.gz)
3392 kwsys_stl::string
SystemTools::GetFilenameLastExtension(const kwsys_stl::string
& filename
)
3394 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3395 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
3396 if(dot_pos
!= kwsys_stl::string::npos
)
3398 return name
.substr(dot_pos
);
3407 * Return file name without extension of a full filename (i.e. without path).
3408 * Warning: it considers the longest extension (for example: .tar.gz)
3410 kwsys_stl::string
SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string
& filename
)
3412 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3413 kwsys_stl::string::size_type dot_pos
= name
.find(".");
3414 if(dot_pos
!= kwsys_stl::string::npos
)
3416 return name
.substr(0, dot_pos
);
3426 * Return file name without extension of a full filename (i.e. without path).
3427 * Warning: it considers the last extension (for example: removes .gz
3431 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string
& filename
)
3433 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3434 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
3435 if(dot_pos
!= kwsys_stl::string::npos
)
3437 return name
.substr(0, dot_pos
);
3445 bool SystemTools::FileHasSignature(const char *filename
,
3446 const char *signature
,
3449 if (!filename
|| !signature
)
3455 fp
= fopen(filename
, "rb");
3461 fseek(fp
, offset
, SEEK_SET
);
3464 size_t signature_len
= strlen(signature
);
3465 char *buffer
= new char [signature_len
];
3467 if (fread(buffer
, 1, signature_len
, fp
) == signature_len
)
3469 res
= (!strncmp(buffer
, signature
, signature_len
) ? true : false);
3478 SystemTools::FileTypeEnum
3479 SystemTools::DetectFileType(const char *filename
,
3480 unsigned long length
,
3483 if (!filename
|| percent_bin
< 0)
3485 return SystemTools::FileTypeUnknown
;
3489 fp
= fopen(filename
, "rb");
3492 return SystemTools::FileTypeUnknown
;
3495 // Allocate buffer and read bytes
3497 unsigned char *buffer
= new unsigned char [length
];
3498 size_t read_length
= fread(buffer
, 1, length
, fp
);
3500 if (read_length
== 0)
3502 return SystemTools::FileTypeUnknown
;
3505 // Loop over contents and count
3507 size_t text_count
= 0;
3509 const unsigned char *ptr
= buffer
;
3510 const unsigned char *buffer_end
= buffer
+ read_length
;
3512 while (ptr
!= buffer_end
)
3514 if ((*ptr
>= 0x20 && *ptr
<= 0x7F) ||
3526 double current_percent_bin
=
3527 (static_cast<double>(read_length
- text_count
) /
3528 static_cast<double>(read_length
));
3530 if (current_percent_bin
>= percent_bin
)
3532 return SystemTools::FileTypeBinary
;
3535 return SystemTools::FileTypeText
;
3538 bool SystemTools::LocateFileInDir(const char *filename
,
3540 kwsys_stl::string
& filename_found
,
3541 int try_filename_dirs
)
3543 if (!filename
|| !dir
)
3548 // Get the basename of 'filename'
3550 kwsys_stl::string filename_base
= SystemTools::GetFilenameName(filename
);
3552 // Check if 'dir' is really a directory
3553 // If win32 and matches something like C:, accept it as a dir
3555 kwsys_stl::string real_dir
;
3556 if (!SystemTools::FileIsDirectory(dir
))
3558 #if defined( _WIN32 )
3559 size_t dir_len
= strlen(dir
);
3560 if (dir_len
< 2 || dir
[dir_len
- 1] != ':')
3563 real_dir
= SystemTools::GetFilenamePath(dir
);
3564 dir
= real_dir
.c_str();
3565 #if defined( _WIN32 )
3570 // Try to find the file in 'dir'
3573 if (filename_base
.size() && dir
)
3575 size_t dir_len
= strlen(dir
);
3577 (dir_len
&& dir
[dir_len
- 1] != '/' && dir
[dir_len
- 1] != '\\');
3579 kwsys_stl::string temp
= dir
;
3584 temp
+= filename_base
;
3586 if (SystemTools::FileExists(temp
.c_str()))
3589 filename_found
= temp
;
3592 // If not found, we can try harder by appending part of the file to
3593 // to the directory to look inside.
3594 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
3595 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
3597 else if (try_filename_dirs
)
3599 kwsys_stl::string
filename_dir(filename
);
3600 kwsys_stl::string filename_dir_base
;
3601 kwsys_stl::string filename_dir_bases
;
3604 filename_dir
= SystemTools::GetFilenamePath(filename_dir
);
3605 filename_dir_base
= SystemTools::GetFilenameName(filename_dir
);
3606 #if defined( _WIN32 )
3607 if (!filename_dir_base
.size() ||
3608 filename_dir_base
[filename_dir_base
.size() - 1] == ':')
3610 if (!filename_dir_base
.size())
3616 filename_dir_bases
= filename_dir_base
+ "/" + filename_dir_bases
;
3623 temp
+= filename_dir_bases
;
3625 res
= SystemTools::LocateFileInDir(
3626 filename_base
.c_str(), temp
.c_str(), filename_found
, 0);
3628 } while (!res
&& filename_dir_base
.size());
3635 bool SystemTools::FileIsFullPath(const char* in_name
)
3637 kwsys_stl::string name
= in_name
;
3638 #if defined(_WIN32) || defined(__CYGWIN__)
3639 // On Windows, the name must be at least two characters long.
3640 if(name
.length() < 2)
3653 // On UNIX, the name must be at least one character long.
3654 if(name
.length() < 1)
3659 #if !defined(_WIN32)
3665 // On UNIX, the name must begin in a '/'.
3666 // On Windows, if the name begins in a '/', then it is a full
3675 bool SystemTools::GetShortPath(const char* path
, kwsys_stl::string
& shortPath
)
3677 #if defined(WIN32) && !defined(__CYGWIN__)
3678 const int size
= int(strlen(path
)) +1; // size of return
3679 char *buffer
= new char[size
]; // create a buffer
3680 char *tempPath
= new char[size
]; // create a buffer
3683 // if the path passed in has quotes around it, first remove the quotes
3684 if (path
[0] == '"' && path
[strlen(path
)-1] == '"')
3686 strcpy(tempPath
,path
+1);
3687 tempPath
[strlen(tempPath
)-1] = '\0';
3691 strcpy(tempPath
,path
);
3695 ret
= GetShortPathName(tempPath
, buffer
, size
);
3697 if(buffer
[0] == 0 || ret
> size
)
3716 void SystemTools::SplitProgramFromArgs(const char* path
,
3717 kwsys_stl::string
& program
, kwsys_stl::string
& args
)
3719 // see if this is a full path to a program
3720 // if so then set program to path and args to nothing
3721 if(SystemTools::FileExists(path
))
3727 // Try to find the program in the path, note the program
3728 // may have spaces in its name so we have to look for it
3729 kwsys_stl::vector
<kwsys_stl::string
> e
;
3730 kwsys_stl::string findProg
= SystemTools::FindProgram(path
, e
);
3738 // Now try and peel off space separated chunks from the end of the string
3739 // so the largest path possible is found allowing for spaces in the path
3740 kwsys_stl::string dir
= path
;
3741 kwsys_stl::string::size_type spacePos
= dir
.rfind(' ');
3742 while(spacePos
!= kwsys_stl::string::npos
)
3744 kwsys_stl::string tryProg
= dir
.substr(0, spacePos
);
3745 // See if the file exists
3746 if(SystemTools::FileExists(tryProg
.c_str()))
3749 // remove trailing spaces from program
3750 kwsys_stl::string::size_type pos
= program
.size()-1;
3751 while(program
[pos
] == ' ')
3756 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
3759 // Now try and find the the program in the path
3760 findProg
= SystemTools::FindProgram(tryProg
.c_str(), e
);
3764 // remove trailing spaces from program
3765 kwsys_stl::string::size_type pos
= program
.size()-1;
3766 while(program
[pos
] == ' ')
3771 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
3774 // move past the space for the next search
3776 spacePos
= dir
.rfind(' ', spacePos
);
3783 kwsys_stl::string
SystemTools::GetCurrentDateTime(const char* format
)
3788 strftime(buf
, sizeof(buf
), format
, localtime(&t
));
3789 return kwsys_stl::string(buf
);
3792 kwsys_stl::string
SystemTools::MakeCindentifier(const char* s
)
3794 kwsys_stl::string
str(s
);
3795 if (str
.find_first_of("0123456789") == 0)
3800 kwsys_stl::string
permited_chars("_"
3801 "abcdefghijklmnopqrstuvwxyz"
3802 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3804 kwsys_stl::string::size_type pos
= 0;
3805 while ((pos
= str
.find_first_not_of(permited_chars
, pos
)) != kwsys_stl::string::npos
)
3812 // Due to a buggy stream library on the HP and another on Mac OS X, we
3813 // need this very carefully written version of getline. Returns true
3814 // if any data were read before the end-of-file was reached.
3815 bool SystemTools::GetLineFromStream(kwsys_ios::istream
& is
,
3816 kwsys_stl::string
& line
,
3817 bool* has_newline
/* = 0 */,
3818 long sizeLimit
/* = -1 */)
3820 const int bufferSize
= 1024;
3821 char buffer
[bufferSize
];
3822 bool haveData
= false;
3823 bool haveNewline
= false;
3825 // Start with an empty line.
3828 long leftToRead
= sizeLimit
;
3830 // If no characters are read from the stream, the end of file has
3831 // been reached. Clear the fail bit just before reading.
3832 while(!haveNewline
&&
3834 (is
.clear(is
.rdstate() & ~kwsys_ios::ios::failbit
),
3835 is
.getline(buffer
, bufferSize
), is
.gcount() > 0))
3837 // We have read at least one byte.
3840 // If newline character was read the gcount includes the character
3841 // but the buffer does not: the end of line has been reached.
3842 size_t length
= strlen(buffer
);
3843 if(length
< static_cast<size_t>(is
.gcount()))
3848 // Avoid storing a carriage return character.
3849 if(length
> 0 && buffer
[length
-1] == '\r')
3851 buffer
[length
-1] = 0;
3854 // if we read too much then truncate the buffer
3857 if (static_cast<long>(length
) > leftToRead
)
3859 buffer
[leftToRead
-1] = 0;
3864 leftToRead
-= static_cast<long>(length
);
3868 // Append the data read to the line.
3869 line
.append(buffer
);
3870 sizeLimit
= sizeLimit
- static_cast<long>(length
);
3873 // Return the results.
3876 *has_newline
= haveNewline
;
3881 int SystemTools::GetTerminalWidth()
3884 #ifdef HAVE_TTY_INFO
3886 char *columns
; /* Unix98 environment variable */
3887 if(ioctl(1, TIOCGWINSZ
, &ws
) != -1 && ws
.ws_col
>0 && ws
.ws_row
>0)
3891 if(!isatty(STDOUT_FILENO
))
3895 columns
= getenv("COLUMNS");
3896 if(columns
&& *columns
)
3900 t
= strtol(columns
, &endptr
, 0);
3901 if(endptr
&& !*endptr
&& (t
>0) && (t
<1000))
3903 width
= static_cast<int>(t
);
3914 bool SystemTools::GetPermissions(const char* file
, mode_t
& mode
)
3922 if ( stat(file
, &st
) < 0 )
3930 bool SystemTools::SetPermissions(const char* file
, mode_t mode
)
3936 if ( !SystemTools::FileExists(file
) )
3940 if ( chmod(file
, mode
) < 0 )
3948 kwsys_stl::string
SystemTools::GetParentDirectory(const char* fileOrDir
)
3950 if ( !fileOrDir
|| !*fileOrDir
)
3954 kwsys_stl::string res
= fileOrDir
;
3955 SystemTools::ConvertToUnixSlashes(res
);
3956 kwsys_stl::string::size_type cc
= res
.size()-1;
3957 if ( res
[cc
] == '/' )
3961 for ( ; cc
> 0; cc
-- )
3963 if ( res
[cc
] == '/' )
3968 return res
.substr(0, cc
);
3971 bool SystemTools::IsSubDirectory(const char* cSubdir
, const char* cDir
)
3973 kwsys_stl::string subdir
= cSubdir
;
3974 kwsys_stl::string dir
= cDir
;
3975 SystemTools::ConvertToUnixSlashes(dir
);
3976 kwsys_stl::string path
= subdir
;
3979 path
= SystemTools::GetParentDirectory(path
.c_str());
3980 if(SystemTools::ComparePath(dir
.c_str(), path
.c_str()))
3985 while ( path
.size() > dir
.size() );
3989 kwsys_stl::string
SystemTools::FileExistsInParentDirectories(const char* fname
,
3990 const char* directory
, const char* toplevel
)
3992 kwsys_stl::string file
= fname
;
3993 SystemTools::ConvertToUnixSlashes(file
);
3994 kwsys_stl::string dir
= directory
;
3995 SystemTools::ConvertToUnixSlashes(dir
);
3996 while ( !dir
.empty() )
3998 kwsys_stl::string path
= dir
+ "/" + file
;
3999 if ( SystemTools::FileExists(path
.c_str()) )
4003 if ( dir
.size() < strlen(toplevel
) )
4007 dir
= SystemTools::GetParentDirectory(dir
.c_str());
4012 void SystemTools::Delay(unsigned int msec
)
4017 // The sleep function gives 1 second resolution and the usleep
4018 // function gives 1e-6 second resolution but on some platforms has a
4019 // maximum sleep time of 1 second. This could be re-implemented to
4020 // use select with masked signals or pselect to mask signals
4021 // atomically. If select is given empty sets and zero as the max
4022 // file descriptor but a non-zero timeout it can be used to block
4023 // for a precise amount of time.
4027 usleep((msec
% 1000) * 1000);
4031 usleep(msec
* 1000);
4036 void SystemTools::ConvertWindowsCommandLineToUnixArguments(
4037 const char *cmd_line
, int *argc
, char ***argv
)
4039 if (!cmd_line
|| !argc
|| !argv
)
4044 // A space delimites an argument except when it is inside a quote
4048 size_t cmd_line_len
= strlen(cmd_line
);
4051 for (i
= 0; i
< cmd_line_len
; i
++)
4053 while (isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4057 if (i
< cmd_line_len
)
4059 if (cmd_line
[i
] == '\"')
4062 while (cmd_line
[i
] != '\"' && i
< cmd_line_len
)
4070 while (!isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4079 (*argv
) = new char* [(*argc
) + 1];
4080 (*argv
)[(*argc
)] = NULL
;
4082 // Set the first arg to be the exec name
4084 (*argv
)[0] = new char [1024];
4086 ::GetModuleFileName(0, (*argv
)[0], 1024);
4088 (*argv
)[0][0] = '\0';
4091 // Allocate the others
4094 for (j
= 1; j
< (*argc
); j
++)
4096 (*argv
)[j
] = new char [cmd_line_len
+ 10];
4104 for (i
= 0; i
< cmd_line_len
; i
++)
4106 while (isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4110 if (i
< cmd_line_len
)
4112 if (cmd_line
[i
] == '\"')
4116 while (cmd_line
[i
] != '\"' && i
< cmd_line_len
)
4120 memcpy((*argv
)[argc_idx
], &cmd_line
[pos
], i
- pos
);
4121 (*argv
)[argc_idx
][i
- pos
] = '\0';
4127 while (!isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4131 memcpy((*argv
)[argc_idx
], &cmd_line
[pos
], i
- pos
);
4132 (*argv
)[argc_idx
][i
- pos
] = '\0';
4139 kwsys_stl::string
SystemTools::GetOperatingSystemNameAndVersion()
4141 kwsys_stl::string res
;
4146 OSVERSIONINFOEX osvi
;
4147 BOOL bOsVersionInfoEx
;
4149 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
4150 // If that fails, try using the OSVERSIONINFO structure.
4152 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
4153 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
4155 bOsVersionInfoEx
= GetVersionEx((OSVERSIONINFO
*)&osvi
);
4156 if (!bOsVersionInfoEx
)
4158 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
4159 if (!GetVersionEx((OSVERSIONINFO
*)&osvi
))
4165 switch (osvi
.dwPlatformId
)
4167 // Test for the Windows NT product family.
4169 case VER_PLATFORM_WIN32_NT
:
4171 // Test for the specific product family.
4173 if (osvi
.dwMajorVersion
== 6 && osvi
.dwMinorVersion
== 0)
4175 #if (_MSC_VER >= 1300)
4176 if (osvi
.wProductType
== VER_NT_WORKSTATION
)
4178 res
+= "Microsoft Windows Vista";
4182 res
+= "Microsoft Windows Server 2008 family";
4185 res
+= "Microsoft Windows Vista or Windows Server 2008";
4189 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
4191 res
+= "Microsoft Windows Server 2003 family";
4194 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
4196 res
+= "Microsoft Windows XP";
4199 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
4201 res
+= "Microsoft Windows 2000";
4204 if (osvi
.dwMajorVersion
<= 4)
4206 res
+= "Microsoft Windows NT";
4209 // Test for specific product on Windows NT 4.0 SP6 and later.
4211 if (bOsVersionInfoEx
)
4213 // Test for the workstation type.
4215 #if (_MSC_VER >= 1300)
4216 if (osvi
.wProductType
== VER_NT_WORKSTATION
)
4218 if (osvi
.dwMajorVersion
== 4)
4220 res
+= " Workstation 4.0";
4222 else if (osvi
.dwMajorVersion
== 5)
4224 if (osvi
.wSuiteMask
& VER_SUITE_PERSONAL
)
4226 res
+= " Home Edition";
4230 res
+= " Professional";
4235 // Test for the server type.
4237 else if (osvi
.wProductType
== VER_NT_SERVER
)
4239 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
4241 if (osvi
.wSuiteMask
& VER_SUITE_DATACENTER
)
4243 res
+= " Datacenter Edition";
4245 else if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
4247 res
+= " Enterprise Edition";
4249 else if (osvi
.wSuiteMask
== VER_SUITE_BLADE
)
4251 res
+= " Web Edition";
4255 res
+= " Standard Edition";
4259 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
4261 if (osvi
.wSuiteMask
& VER_SUITE_DATACENTER
)
4263 res
+= " Datacenter Server";
4265 else if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
4267 res
+= " Advanced Server";
4275 else if (osvi
.dwMajorVersion
<= 4) // Windows NT 4.0
4277 if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
4279 res
+= " Server 4.0, Enterprise Edition";
4283 res
+= " Server 4.0";
4287 #endif // Visual Studio 7 and up
4290 // Test for specific product on Windows NT 4.0 SP5 and earlier
4296 char szProductType
[BUFSIZE
];
4297 DWORD dwBufLen
=BUFSIZE
;
4300 lRet
= RegOpenKeyEx(
4302 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
4303 0, KEY_QUERY_VALUE
, &hKey
);
4304 if (lRet
!= ERROR_SUCCESS
)
4309 lRet
= RegQueryValueEx(hKey
, "ProductType", NULL
, NULL
,
4310 (LPBYTE
) szProductType
, &dwBufLen
);
4312 if ((lRet
!= ERROR_SUCCESS
) || (dwBufLen
> BUFSIZE
))
4319 if (lstrcmpi("WINNT", szProductType
) == 0)
4321 res
+= " Workstation";
4323 if (lstrcmpi("LANMANNT", szProductType
) == 0)
4327 if (lstrcmpi("SERVERNT", szProductType
) == 0)
4329 res
+= " Advanced Server";
4333 sprintf(buffer
, "%ld", osvi
.dwMajorVersion
);
4336 sprintf(buffer
, "%ld", osvi
.dwMinorVersion
);
4340 // Display service pack (if any) and build number.
4342 if (osvi
.dwMajorVersion
== 4 &&
4343 lstrcmpi(osvi
.szCSDVersion
, "Service Pack 6") == 0)
4348 // Test for SP6 versus SP6a.
4350 lRet
= RegOpenKeyEx(
4352 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
4353 0, KEY_QUERY_VALUE
, &hKey
);
4355 if (lRet
== ERROR_SUCCESS
)
4357 res
+= " Service Pack 6a (Build ";
4358 sprintf(buffer
, "%ld", osvi
.dwBuildNumber
& 0xFFFF);
4362 else // Windows NT 4.0 prior to SP6a
4365 res
+= osvi
.szCSDVersion
;
4367 sprintf(buffer
, "%ld", osvi
.dwBuildNumber
& 0xFFFF);
4374 else // Windows NT 3.51 and earlier or Windows 2000 and later
4377 res
+= osvi
.szCSDVersion
;
4379 sprintf(buffer
, "%ld", osvi
.dwBuildNumber
& 0xFFFF);
4386 // Test for the Windows 95 product family.
4388 case VER_PLATFORM_WIN32_WINDOWS
:
4390 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
4392 res
+= "Microsoft Windows 95";
4393 if (osvi
.szCSDVersion
[1] == 'C' || osvi
.szCSDVersion
[1] == 'B')
4399 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
4401 res
+= "Microsoft Windows 98";
4402 if (osvi
.szCSDVersion
[1] == 'A')
4408 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
4410 res
+= "Microsoft Windows Millennium Edition";
4414 case VER_PLATFORM_WIN32s
:
4416 res
+= "Microsoft Win32s";
4424 // ----------------------------------------------------------------------
4425 bool SystemTools::ParseURLProtocol( const kwsys_stl::string
& URL
,
4426 kwsys_stl::string
& protocol
,
4427 kwsys_stl::string
& dataglom
)
4429 // match 0 entire url
4431 // match 2 dataglom following protocol://
4432 kwsys::RegularExpression
urlRe( VTK_URL_PROTOCOL_REGEX
);
4434 if ( ! urlRe
.find( URL
) ) return false;
4436 protocol
= urlRe
.match( 1 );
4437 dataglom
= urlRe
.match( 2 );
4442 // ----------------------------------------------------------------------
4443 bool SystemTools::ParseURL( const kwsys_stl::string
& URL
,
4444 kwsys_stl::string
& protocol
,
4445 kwsys_stl::string
& username
,
4446 kwsys_stl::string
& password
,
4447 kwsys_stl::string
& hostname
,
4448 kwsys_stl::string
& dataport
,
4449 kwsys_stl::string
& database
)
4451 kwsys::RegularExpression
urlRe( VTK_URL_REGEX
);
4452 if ( ! urlRe
.find( URL
) ) return false;
4456 // match 2 mangled user
4458 // match 4 mangled password
4461 // match 7 mangled port
4463 // match 9 database name
4465 protocol
= urlRe
.match( 1 );
4466 username
= urlRe
.match( 3 );
4467 password
= urlRe
.match( 5 );
4468 hostname
= urlRe
.match( 6 );
4469 dataport
= urlRe
.match( 8 );
4470 database
= urlRe
.match( 9 );
4475 // ----------------------------------------------------------------------
4476 // These must NOT be initialized. Default initialization to zero is
4478 unsigned int SystemToolsManagerCount
;
4479 SystemToolsTranslationMap
*SystemTools::TranslationMap
;
4480 SystemToolsTranslationMap
*SystemTools::LongPathMap
;
4482 // SystemToolsManager manages the SystemTools singleton.
4483 // SystemToolsManager should be included in any translation unit
4484 // that will use SystemTools or that implements the singleton
4485 // pattern. It makes sure that the SystemTools singleton is created
4486 // before and destroyed after all other singletons in CMake.
4488 SystemToolsManager::SystemToolsManager()
4490 if(++SystemToolsManagerCount
== 1)
4492 SystemTools::ClassInitialize();
4496 SystemToolsManager::~SystemToolsManager()
4498 if(--SystemToolsManagerCount
== 0)
4500 SystemTools::ClassFinalize();
4504 void SystemTools::ClassInitialize()
4506 // Allocate the translation map first.
4507 SystemTools::TranslationMap
= new SystemToolsTranslationMap
;
4508 SystemTools::LongPathMap
= new SystemToolsTranslationMap
;
4510 // Add some special translation paths for unix. These are not added
4511 // for windows because drive letters need to be maintained. Also,
4512 // there are not sym-links and mount points on windows anyway.
4513 #if !defined(_WIN32) || defined(__CYGWIN__)
4514 // Work-around an SGI problem by always adding this mapping:
4515 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
4516 // The tmp path is frequently a logical path so always keep it:
4517 SystemTools::AddKeepPath("/tmp/");
4519 // If the current working directory is a logical path then keep the
4521 if(const char* pwd
= getenv("PWD"))
4524 if(const char* cwd
= Getcwd(buf
, 2048))
4526 // The current working directory may be a logical path. Find
4527 // the shortest logical path that still produces the correct
4529 kwsys_stl::string cwd_changed
;
4530 kwsys_stl::string pwd_changed
;
4532 // Test progressively shorter logical-to-physical mappings.
4533 kwsys_stl::string pwd_str
= pwd
;
4534 kwsys_stl::string cwd_str
= cwd
;
4535 kwsys_stl::string pwd_path
;
4536 Realpath(pwd
, pwd_path
);
4537 while(cwd_str
== pwd_path
&& cwd_str
!= pwd_str
)
4539 // The current pair of paths is a working logical mapping.
4540 cwd_changed
= cwd_str
;
4541 pwd_changed
= pwd_str
;
4543 // Strip off one directory level and see if the logical
4544 // mapping still works.
4545 pwd_str
= SystemTools::GetFilenamePath(pwd_str
.c_str());
4546 cwd_str
= SystemTools::GetFilenamePath(cwd_str
.c_str());
4547 Realpath(pwd_str
.c_str(), pwd_path
);
4550 // Add the translation to keep the logical path name.
4551 if(!cwd_changed
.empty() && !pwd_changed
.empty())
4553 SystemTools::AddTranslationPath(cwd_changed
.c_str(),
4554 pwd_changed
.c_str());
4561 void SystemTools::ClassFinalize()
4563 delete SystemTools::TranslationMap
;
4564 delete SystemTools::LongPathMap
;
4568 } // namespace KWSYS_NAMESPACE
4570 #if defined(_MSC_VER) && defined(_DEBUG)
4571 # include <crtdbg.h>
4573 # include <stdlib.h>
4574 namespace KWSYS_NAMESPACE
4577 static int SystemToolsDebugReport(int, char* message
, int*)
4579 fprintf(stderr
, "%s", message
);
4581 return 1; // no further reporting required
4584 void SystemTools::EnableMSVCDebugHook()
4586 if (getenv("DART_TEST_FROM_DART"))
4588 _CrtSetReportHook(SystemToolsDebugReport
);
4592 } // namespace KWSYS_NAMESPACE
4594 namespace KWSYS_NAMESPACE
4596 void SystemTools::EnableMSVCDebugHook() {}
4597 } // namespace KWSYS_NAMESPACE