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 resolved_path
= path
;
214 #include <sys/types.h>
217 inline int Mkdir(const char* dir
)
219 return mkdir(dir
, 00777);
221 inline int Rmdir(const char* dir
)
225 inline const char* Getcwd(char* buf
, unsigned int len
)
227 const char* ret
= getcwd(buf
, len
);
230 fprintf(stderr
, "No current working directory\n");
236 inline int Chdir(const char* dir
)
240 inline void Realpath(const char *path
, kwsys_stl::string
& resolved_path
)
242 char resolved_name
[KWSYS_SYSTEMTOOLS_MAXPATH
];
244 char *ret
= realpath(path
, resolved_name
);
251 // if path resolution fails, return what was passed in
252 resolved_path
= path
;
257 #if !defined(_WIN32) && defined(__COMO__)
258 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
261 extern FILE *popen (__const
char *__command
, __const
char *__modes
) __THROW
;
262 extern int pclose (FILE *__stream
) __THROW
;
263 extern char *realpath (__const
char *__restrict __name
,
264 char *__restrict __resolved
) __THROW
;
265 extern char *strdup (__const
char *__s
) __THROW
;
266 extern int putenv (char *__string
) __THROW
;
270 /* Implement floattime() for various platforms */
271 // Taken from Python 2.1.3
273 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
274 # include <sys/timeb.h>
276 # if defined( __BORLANDC__)
279 # else // Visual studio?
280 # define FTIME _ftime
281 # define TIMEB _timeb
283 #elif defined( __CYGWIN__ ) || defined( __linux__ )
284 # include <sys/time.h>
286 # define HAVE_GETTIMEOFDAY
289 namespace KWSYS_NAMESPACE
292 class SystemToolsTranslationMap
:
293 public kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>
299 SystemTools::GetTime(void)
301 /* There are three ways to get the time:
302 (1) gettimeofday() -- resolution in microseconds
303 (2) ftime() -- resolution in milliseconds
304 (3) time() -- resolution in seconds
305 In all cases the return value is a float in seconds.
306 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
307 fail, so we fall back on ftime() or time().
308 Note: clock resolution does not imply clock accuracy! */
309 #ifdef HAVE_GETTIMEOFDAY
312 #ifdef GETTIMEOFDAY_NO_TZ
313 if (gettimeofday(&t
) == 0)
314 #else /* !GETTIMEOFDAY_NO_TZ */
315 if (gettimeofday(&t
, static_cast<struct timezone
*>(NULL
)) == 0)
316 #endif /* !GETTIMEOFDAY_NO_TZ */
317 return static_cast<double>(t
.tv_sec
) +
318 static_cast<double>(t
.tv_usec
)*0.000001;
320 #endif /* !HAVE_GETTIMEOFDAY */
322 #if defined(HAVE_FTIME)
325 return static_cast<double>(t
.time
) +
326 static_cast<double>(t
.millitm
) * static_cast<double>(0.001);
327 #else /* !HAVE_FTIME */
330 return static_cast<double>(secs
);
331 #endif /* !HAVE_FTIME */
335 // adds the elements of the env variable path to the arg passed in
336 void SystemTools::GetPath(kwsys_stl::vector
<kwsys_stl::string
>& path
, const char* env
)
338 #if defined(_WIN32) && !defined(__CYGWIN__)
339 const char* pathSep
= ";";
341 const char* pathSep
= ":";
347 const char* cpathEnv
= SystemTools::GetEnv(env
);
353 kwsys_stl::string pathEnv
= cpathEnv
;
355 // A hack to make the below algorithm work.
356 if(pathEnv
[pathEnv
.length()-1] != ':')
360 kwsys_stl::string::size_type start
=0;
364 kwsys_stl::string::size_type endpos
= pathEnv
.find(pathSep
, start
);
365 if(endpos
!= kwsys_stl::string::npos
)
367 kwsys_stl::string convertedPath
;
368 Realpath(pathEnv
.substr(start
, endpos
-start
).c_str(), convertedPath
);
369 path
.push_back(convertedPath
);
377 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
378 i
!= path
.end(); ++i
)
380 SystemTools::ConvertToUnixSlashes(*i
);
384 const char* SystemTools::GetEnv(const char* key
)
389 bool SystemTools::GetEnv(const char* key
, kwsys_stl::string
& result
)
391 const char* v
= getenv(key
);
403 const char* SystemTools::GetExecutableExtension()
405 #if defined(_WIN32) || defined(__CYGWIN__)
413 bool SystemTools::MakeDirectory(const char* path
)
419 if(SystemTools::FileExists(path
))
423 kwsys_stl::string dir
= path
;
428 SystemTools::ConvertToUnixSlashes(dir
);
430 kwsys_stl::string::size_type pos
= dir
.find(':');
431 if(pos
== kwsys_stl::string::npos
)
435 kwsys_stl::string topdir
;
436 while((pos
= dir
.find('/', pos
)) != kwsys_stl::string::npos
)
438 topdir
= dir
.substr(0, pos
);
439 Mkdir(topdir
.c_str());
442 if(dir
[dir
.size()-1] == '/')
444 topdir
= dir
.substr(0, dir
.size());
450 if(Mkdir(topdir
.c_str()) != 0)
452 // There is a bug in the Borland Run time library which makes MKDIR
453 // return EACCES when it should return EEXISTS
454 // if it is some other error besides directory exists
456 if( (errno
!= EEXIST
)
469 // replace replace with with as many times as it shows up in source.
470 // write the result into source.
471 void SystemTools::ReplaceString(kwsys_stl::string
& source
,
475 const char *src
= source
.c_str();
476 char *searchPos
= const_cast<char *>(strstr(src
,replace
));
478 // get out quick if string is not found
484 // perform replacements until done
485 size_t replaceSize
= strlen(replace
);
486 // do while hangs if replaceSize is 0
491 char *orig
= strdup(src
);
492 char *currentPos
= orig
;
493 searchPos
= searchPos
- src
+ orig
;
495 // initialize the result
496 source
.erase(source
.begin(),source
.end());
500 source
+= currentPos
;
501 currentPos
= searchPos
+ replaceSize
;
504 searchPos
= strstr(currentPos
,replace
);
508 // copy any trailing text
509 source
+= currentPos
;
513 #if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
514 # define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
515 # define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
517 # define KWSYS_ST_KEY_WOW64_32KEY 0x0200
518 # define KWSYS_ST_KEY_WOW64_64KEY 0x0100
521 #if defined(_WIN32) && !defined(__CYGWIN__)
522 static DWORD
SystemToolsMakeRegistryMode(DWORD mode
,
523 SystemTools::KeyWOW64 view
)
525 if(view
== SystemTools::KeyWOW64_32
)
527 return mode
| KWSYS_ST_KEY_WOW64_32KEY
;
529 else if(view
== SystemTools::KeyWOW64_64
)
531 return mode
| KWSYS_ST_KEY_WOW64_64KEY
;
537 // Read a registry value.
539 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
540 // => will return the data of the "default" value of the key
541 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
542 // => will return the data of the "Root" value of the key
544 #if defined(_WIN32) && !defined(__CYGWIN__)
545 bool SystemTools::ReadRegistryValue(const char *key
, kwsys_stl::string
&value
,
548 bool valueset
= false;
549 kwsys_stl::string primary
= key
;
550 kwsys_stl::string second
;
551 kwsys_stl::string valuename
;
553 size_t start
= primary
.find("\\");
554 if (start
== kwsys_stl::string::npos
)
559 size_t valuenamepos
= primary
.find(";");
560 if (valuenamepos
!= kwsys_stl::string::npos
)
562 valuename
= primary
.substr(valuenamepos
+1);
565 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
566 primary
= primary
.substr(0, start
);
568 HKEY primaryKey
= HKEY_CURRENT_USER
;
569 if (primary
== "HKEY_CURRENT_USER")
571 primaryKey
= HKEY_CURRENT_USER
;
573 if (primary
== "HKEY_CURRENT_CONFIG")
575 primaryKey
= HKEY_CURRENT_CONFIG
;
577 if (primary
== "HKEY_CLASSES_ROOT")
579 primaryKey
= HKEY_CLASSES_ROOT
;
581 if (primary
== "HKEY_LOCAL_MACHINE")
583 primaryKey
= HKEY_LOCAL_MACHINE
;
585 if (primary
== "HKEY_USERS")
587 primaryKey
= HKEY_USERS
;
591 if(RegOpenKeyEx(primaryKey
,
594 SystemToolsMakeRegistryMode(KEY_READ
, view
),
595 &hKey
) != ERROR_SUCCESS
)
601 DWORD dwType
, dwSize
;
604 if(RegQueryValueEx(hKey
,
605 (LPTSTR
)valuename
.c_str(),
609 &dwSize
) == ERROR_SUCCESS
)
611 if (dwType
== REG_SZ
)
616 else if (dwType
== REG_EXPAND_SZ
)
619 DWORD dwExpandedSize
= sizeof(expanded
)/sizeof(expanded
[0]);
620 if(ExpandEnvironmentStrings(data
, expanded
, dwExpandedSize
))
634 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string
&,
642 // Write a registry value.
644 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
645 // => will set the data of the "default" value of the key
646 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
647 // => will set the data of the "Root" value of the key
649 #if defined(_WIN32) && !defined(__CYGWIN__)
650 bool SystemTools::WriteRegistryValue(const char *key
, const char *value
,
653 kwsys_stl::string primary
= key
;
654 kwsys_stl::string second
;
655 kwsys_stl::string valuename
;
657 size_t start
= primary
.find("\\");
658 if (start
== kwsys_stl::string::npos
)
663 size_t valuenamepos
= primary
.find(";");
664 if (valuenamepos
!= kwsys_stl::string::npos
)
666 valuename
= primary
.substr(valuenamepos
+1);
669 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
670 primary
= primary
.substr(0, start
);
672 HKEY primaryKey
= HKEY_CURRENT_USER
;
673 if (primary
== "HKEY_CURRENT_USER")
675 primaryKey
= HKEY_CURRENT_USER
;
677 if (primary
== "HKEY_CURRENT_CONFIG")
679 primaryKey
= HKEY_CURRENT_CONFIG
;
681 if (primary
== "HKEY_CLASSES_ROOT")
683 primaryKey
= HKEY_CLASSES_ROOT
;
685 if (primary
== "HKEY_LOCAL_MACHINE")
687 primaryKey
= HKEY_LOCAL_MACHINE
;
689 if (primary
== "HKEY_USERS")
691 primaryKey
= HKEY_USERS
;
696 if(RegCreateKeyEx(primaryKey
,
700 REG_OPTION_NON_VOLATILE
,
701 SystemToolsMakeRegistryMode(KEY_WRITE
, view
),
704 &dwDummy
) != ERROR_SUCCESS
)
709 if(RegSetValueEx(hKey
,
710 (LPTSTR
)valuename
.c_str(),
714 (DWORD
)(strlen(value
) + 1)) == ERROR_SUCCESS
)
721 bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64
)
727 // Delete a registry value.
729 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
730 // => will delete the data of the "default" value of the key
731 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
732 // => will delete the data of the "Root" value of the key
734 #if defined(_WIN32) && !defined(__CYGWIN__)
735 bool SystemTools::DeleteRegistryValue(const char *key
, KeyWOW64 view
)
737 kwsys_stl::string primary
= key
;
738 kwsys_stl::string second
;
739 kwsys_stl::string valuename
;
741 size_t start
= primary
.find("\\");
742 if (start
== kwsys_stl::string::npos
)
747 size_t valuenamepos
= primary
.find(";");
748 if (valuenamepos
!= kwsys_stl::string::npos
)
750 valuename
= primary
.substr(valuenamepos
+1);
753 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
754 primary
= primary
.substr(0, start
);
756 HKEY primaryKey
= HKEY_CURRENT_USER
;
757 if (primary
== "HKEY_CURRENT_USER")
759 primaryKey
= HKEY_CURRENT_USER
;
761 if (primary
== "HKEY_CURRENT_CONFIG")
763 primaryKey
= HKEY_CURRENT_CONFIG
;
765 if (primary
== "HKEY_CLASSES_ROOT")
767 primaryKey
= HKEY_CLASSES_ROOT
;
769 if (primary
== "HKEY_LOCAL_MACHINE")
771 primaryKey
= HKEY_LOCAL_MACHINE
;
773 if (primary
== "HKEY_USERS")
775 primaryKey
= HKEY_USERS
;
779 if(RegOpenKeyEx(primaryKey
,
782 SystemToolsMakeRegistryMode(KEY_WRITE
, view
),
783 &hKey
) != ERROR_SUCCESS
)
789 if(RegDeleteValue(hKey
,
790 (LPTSTR
)valuename
.c_str()) == ERROR_SUCCESS
)
799 bool SystemTools::DeleteRegistryValue(const char *, KeyWOW64
)
805 bool SystemTools::SameFile(const char* file1
, const char* file2
)
808 HANDLE hFile1
, hFile2
;
810 hFile1
= CreateFile( file1
,
815 FILE_FLAG_BACKUP_SEMANTICS
,
818 hFile2
= CreateFile( file2
,
823 FILE_FLAG_BACKUP_SEMANTICS
,
826 if( hFile1
== INVALID_HANDLE_VALUE
|| hFile2
== INVALID_HANDLE_VALUE
)
828 if(hFile1
!= INVALID_HANDLE_VALUE
)
832 if(hFile2
!= INVALID_HANDLE_VALUE
)
839 BY_HANDLE_FILE_INFORMATION fiBuf1
;
840 BY_HANDLE_FILE_INFORMATION fiBuf2
;
841 GetFileInformationByHandle( hFile1
, &fiBuf1
);
842 GetFileInformationByHandle( hFile2
, &fiBuf2
);
845 return (fiBuf1
.dwVolumeSerialNumber
== fiBuf2
.dwVolumeSerialNumber
&&
846 fiBuf1
.nFileIndexHigh
== fiBuf2
.nFileIndexHigh
&&
847 fiBuf1
.nFileIndexLow
== fiBuf2
.nFileIndexLow
);
849 struct stat fileStat1
, fileStat2
;
850 if (stat(file1
, &fileStat1
) == 0 && stat(file2
, &fileStat2
) == 0)
852 // see if the files are the same file
853 // check the device inode and size
854 if(memcmp(&fileStat2
.st_dev
, &fileStat1
.st_dev
, sizeof(fileStat1
.st_dev
)) == 0 &&
855 memcmp(&fileStat2
.st_ino
, &fileStat1
.st_ino
, sizeof(fileStat1
.st_ino
)) == 0 &&
856 fileStat2
.st_size
== fileStat1
.st_size
867 // return true if the file exists
868 bool SystemTools::FileExists(const char* filename
, bool isFile
)
871 # define access _access
878 if ((filename
!=0) && (*filename
== 0))
884 if ( access(filename
, R_OK
) != 0 )
890 // If isFile is set return not FileIsDirectory,
891 // so this will only be true if it is a file
894 return !SystemTools::FileIsDirectory(filename
);
900 bool SystemTools::Touch(const char* filename
, bool create
)
902 if(create
&& !SystemTools::FileExists(filename
))
904 FILE* file
= fopen(filename
, "a+b");
914 #define utimbuf _utimbuf
916 struct stat fromStat
;
917 if(stat(filename
, &fromStat
) < 0)
922 buf
.actime
= fromStat
.st_atime
;
923 buf
.modtime
= static_cast<time_t>(SystemTools::GetTime());
924 if(utime(filename
, &buf
) < 0)
931 bool SystemTools::FileTimeCompare(const char* f1
, const char* f2
,
934 // Default to same time.
936 #if !defined(_WIN32) || defined(__CYGWIN__)
937 // POSIX version. Use stat function to get file modification time.
939 if(stat(f1
, &s1
) != 0)
944 if(stat(f2
, &s2
) != 0)
948 # if KWSYS_STAT_HAS_ST_MTIM
949 // Compare using nanosecond resolution.
950 if(s1
.st_mtim
.tv_sec
< s2
.st_mtim
.tv_sec
)
954 else if(s1
.st_mtim
.tv_sec
> s2
.st_mtim
.tv_sec
)
958 else if(s1
.st_mtim
.tv_nsec
< s2
.st_mtim
.tv_nsec
)
962 else if(s1
.st_mtim
.tv_nsec
> s2
.st_mtim
.tv_nsec
)
967 // Compare using 1 second resolution.
968 if(s1
.st_mtime
< s2
.st_mtime
)
972 else if(s1
.st_mtime
> s2
.st_mtime
)
978 // Windows version. Get the modification time from extended file attributes.
979 WIN32_FILE_ATTRIBUTE_DATA f1d
;
980 WIN32_FILE_ATTRIBUTE_DATA f2d
;
981 if(!GetFileAttributesEx(f1
, GetFileExInfoStandard
, &f1d
))
985 if(!GetFileAttributesEx(f2
, GetFileExInfoStandard
, &f2d
))
990 // Compare the file times using resolution provided by system call.
991 *result
= (int)CompareFileTime(&f1d
.ftLastWriteTime
, &f2d
.ftLastWriteTime
);
997 // Return a capitalized string (i.e the first letter is uppercased, all other
999 kwsys_stl::string
SystemTools::Capitalized(const kwsys_stl::string
& s
)
1001 kwsys_stl::string n
;
1007 n
[0] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[0]));
1008 for (size_t i
= 1; i
< s
.size(); i
++)
1010 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
1015 // Return capitalized words
1016 kwsys_stl::string
SystemTools::CapitalizedWords(const kwsys_stl::string
& s
)
1018 kwsys_stl::string
n(s
);
1019 for (size_t i
= 0; i
< s
.size(); i
++)
1021 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1022 // MS has an assert that will fail if s[i] < 0; setting
1023 // LC_CTYPE using setlocale() does *not* help. Painful.
1024 if ((int)s
[i
] >= 0 && isalpha(s
[i
]) &&
1025 (i
== 0 || ((int)s
[i
- 1] >= 0 && isspace(s
[i
- 1]))))
1027 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
1030 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
1036 // Return uncapitalized words
1037 kwsys_stl::string
SystemTools::UnCapitalizedWords(const kwsys_stl::string
& s
)
1039 kwsys_stl::string
n(s
);
1040 for (size_t i
= 0; i
< s
.size(); i
++)
1042 #if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
1043 // MS has an assert that will fail if s[i] < 0; setting
1044 // LC_CTYPE using setlocale() does *not* help. Painful.
1045 if ((int)s
[i
] >= 0 && isalpha(s
[i
]) &&
1046 (i
== 0 || ((int)s
[i
- 1] >= 0 && isspace(s
[i
- 1]))))
1048 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
1051 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
1057 // only works for words with at least two letters
1058 kwsys_stl::string
SystemTools::AddSpaceBetweenCapitalizedWords(
1059 const kwsys_stl::string
& s
)
1061 kwsys_stl::string n
;
1064 n
.reserve(s
.size());
1066 for (size_t i
= 1; i
< s
.size(); i
++)
1068 if (isupper(s
[i
]) && !isspace(s
[i
- 1]) && !isupper(s
[i
- 1]))
1078 char* SystemTools::AppendStrings(const char* str1
, const char* str2
)
1082 return SystemTools::DuplicateString(str2
);
1086 return SystemTools::DuplicateString(str1
);
1088 size_t len1
= strlen(str1
);
1089 char *newstr
= new char[len1
+ strlen(str2
) + 1];
1094 strcpy(newstr
, str1
);
1095 strcat(newstr
+ len1
, str2
);
1099 char* SystemTools::AppendStrings(
1100 const char* str1
, const char* str2
, const char* str3
)
1104 return SystemTools::AppendStrings(str2
, str3
);
1108 return SystemTools::AppendStrings(str1
, str3
);
1112 return SystemTools::AppendStrings(str1
, str2
);
1115 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1116 char *newstr
= new char[len1
+ len2
+ strlen(str3
) + 1];
1121 strcpy(newstr
, str1
);
1122 strcat(newstr
+ len1
, str2
);
1123 strcat(newstr
+ len1
+ len2
, str3
);
1127 // Return a lower case string
1128 kwsys_stl::string
SystemTools::LowerCase(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
>(tolower(s
[i
]));
1139 // Return a lower case string
1140 kwsys_stl::string
SystemTools::UpperCase(const kwsys_stl::string
& s
)
1142 kwsys_stl::string n
;
1144 for (size_t i
= 0; i
< s
.size(); i
++)
1146 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
1151 // Count char in string
1152 size_t SystemTools::CountChar(const char* str
, char c
)
1170 // Remove chars in string
1171 char* SystemTools::RemoveChars(const char* str
, const char *toremove
)
1177 char *clean_str
= new char [strlen(str
) + 1];
1178 char *ptr
= clean_str
;
1181 const char *str2
= toremove
;
1182 while (*str2
&& *str
!= *str2
)
1196 // Remove chars in string
1197 char* SystemTools::RemoveCharsButUpperHex(const char* str
)
1203 char *clean_str
= new char [strlen(str
) + 1];
1204 char *ptr
= clean_str
;
1207 if ((*str
>= '0' && *str
<= '9') || (*str
>= 'A' && *str
<= 'F'))
1217 // Replace chars in string
1218 char* SystemTools::ReplaceChars(char* str
, const char *toreplace
, char replacement
)
1225 const char *ptr2
= toreplace
;
1240 // Returns if string starts with another string
1241 bool SystemTools::StringStartsWith(const char* str1
, const char* str2
)
1247 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1248 return len1
>= len2
&& !strncmp(str1
, str2
, len2
) ? true : false;
1251 // Returns if string ends with another string
1252 bool SystemTools::StringEndsWith(const char* str1
, const char* str2
)
1258 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1259 return len1
>= len2
&& !strncmp(str1
+ (len1
- len2
), str2
, len2
) ? true : false;
1262 // Returns a pointer to the last occurence of str2 in str1
1263 const char* SystemTools::FindLastString(const char* str1
, const char* str2
)
1270 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1273 const char *ptr
= str1
+ len1
- len2
;
1276 if (!strncmp(ptr
, str2
, len2
))
1280 } while (ptr
-- != str1
);
1287 char* SystemTools::DuplicateString(const char* str
)
1291 char *newstr
= new char [strlen(str
) + 1];
1292 return strcpy(newstr
, str
);
1297 // Return a cropped string
1298 kwsys_stl::string
SystemTools::CropString(const kwsys_stl::string
& s
,
1301 if (!s
.size() || max_len
== 0 || max_len
>= s
.size())
1306 kwsys_stl::string n
;
1309 size_t middle
= max_len
/ 2;
1311 n
+= s
.substr(0, middle
);
1312 n
+= s
.substr(s
.size() - (max_len
- middle
), kwsys_stl::string::npos
);
1319 n
[middle
- 1] = '.';
1322 n
[middle
+ 1] = '.';
1330 //----------------------------------------------------------------------------
1331 kwsys_stl::vector
<kwsys::String
> SystemTools::SplitString(const char* p
, char sep
, bool isPath
)
1333 kwsys_stl::string path
= p
;
1334 kwsys_stl::vector
<kwsys::String
> paths
;
1335 if(isPath
&& path
[0] == '/')
1337 path
.erase(path
.begin());
1338 paths
.push_back("/");
1340 kwsys_stl::string::size_type pos1
= 0;
1341 kwsys_stl::string::size_type pos2
= path
.find(sep
, pos1
+1);
1342 while(pos2
!= kwsys_stl::string::npos
)
1344 paths
.push_back(path
.substr(pos1
, pos2
-pos1
));
1346 pos2
= path
.find(sep
, pos1
+1);
1348 paths
.push_back(path
.substr(pos1
, pos2
-pos1
));
1353 //----------------------------------------------------------------------------
1354 int SystemTools::EstimateFormatLength(const char *format
, va_list ap
)
1361 // Quick-hack attempt at estimating the length of the string.
1362 // Should never under-estimate.
1364 // Start with the length of the format string itself.
1366 size_t length
= strlen(format
);
1368 // Increase the length for every argument in the format.
1370 const char* cur
= format
;
1375 // Skip "%%" since it doesn't correspond to a va_arg.
1378 while(!int(isalpha(*cur
)))
1386 // Check the length of the string.
1387 char* s
= va_arg(ap
, char*);
1390 length
+= strlen(s
);
1397 // Assume the argument contributes no more than 64 characters.
1400 // Eat the argument.
1401 static_cast<void>(va_arg(ap
, double));
1405 // Assume the argument contributes no more than 64 characters.
1408 // Eat the argument.
1409 static_cast<void>(va_arg(ap
, int));
1414 // Move past the characters just tested.
1419 return static_cast<int>(length
);
1422 kwsys_stl::string
SystemTools::EscapeChars(
1424 const char *chars_to_escape
,
1427 kwsys_stl::string n
;
1430 if (!chars_to_escape
| !*chars_to_escape
)
1436 n
.reserve(strlen(str
));
1439 const char *ptr
= chars_to_escape
;
1457 // convert windows slashes to unix slashes
1458 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string
& path
)
1460 const char* pathCString
= path
.c_str();
1461 bool hasDoubleSlash
= false;
1463 const char* pos0
= pathCString
;
1464 const char* pos1
= pathCString
+1;
1465 for (kwsys_stl::string::size_type pos
= 0; *pos0
; ++ pos
)
1467 // make sure we don't convert an escaped space to a unix slash
1468 if ( *pos0
== '\\' && *pos1
!= ' ' )
1473 // Also, reuse the loop to check for slash followed by another slash
1474 if (*pos1
== '/' && *(pos1
+1) == '/' && !hasDoubleSlash
)
1477 // However, on windows if the first characters are both slashes,
1478 // then keep them that way, so that network paths can be handled.
1481 hasDoubleSlash
= true;
1484 hasDoubleSlash
= true;
1492 if ( hasDoubleSlash
)
1494 SystemTools::ReplaceString(path
, "//", "/");
1497 // remove any trailing slash
1500 // if there is a tilda ~ then replace it with HOME
1501 pathCString
= path
.c_str();
1502 if(pathCString
[0] == '~' && (pathCString
[1] == '/' || pathCString
[1] == '\0'))
1504 const char* homeEnv
= SystemTools::GetEnv("HOME");
1507 path
.replace(0,1,homeEnv
);
1510 #ifdef HAVE_GETPWNAM
1511 else if(pathCString
[0] == '~')
1513 kwsys_stl::string::size_type idx
= path
.find_first_of("/\0");
1514 kwsys_stl::string user
= path
.substr(1, idx
-1);
1515 passwd
* pw
= getpwnam(user
.c_str());
1518 path
.replace(0, idx
, pw
->pw_dir
);
1522 // remove trailing slash if the path is more than
1524 pathCString
= path
.c_str();
1525 if(path
.size() > 1 && *(pathCString
+(path
.size()-1)) == '/')
1527 // if it is c:/ then do not remove the trailing slash
1528 if(!((path
.size() == 3 && pathCString
[1] == ':')))
1530 path
= path
.substr(0, path
.size()-1);
1536 // change // to /, and escape any spaces in the path
1537 kwsys_stl::string
SystemTools::ConvertToUnixOutputPath(const char* path
)
1539 kwsys_stl::string ret
= path
;
1541 // remove // except at the beginning might be a cygwin drive
1542 kwsys_stl::string::size_type pos
=0;
1543 while((pos
= ret
.find("//", pos
)) != kwsys_stl::string::npos
)
1547 // escape spaces and () in the path
1548 if(ret
.find_first_of(" ") != kwsys_stl::string::npos
)
1550 kwsys_stl::string result
= "";
1552 for(const char* ch
= ret
.c_str(); *ch
!= '\0'; ++ch
)
1554 // if it is already escaped then don't try to escape it again
1555 if((*ch
== ' ') && lastch
!= '\\')
1567 kwsys_stl::string
SystemTools::ConvertToOutputPath(const char* path
)
1569 #if defined(_WIN32) && !defined(__CYGWIN__)
1570 return SystemTools::ConvertToWindowsOutputPath(path
);
1572 return SystemTools::ConvertToUnixOutputPath(path
);
1576 // remove double slashes not at the start
1577 kwsys_stl::string
SystemTools::ConvertToWindowsOutputPath(const char* path
)
1579 kwsys_stl::string ret
;
1580 // make it big enough for all of path and double quotes
1581 ret
.reserve(strlen(path
)+3);
1582 // put path into the string
1585 kwsys_stl::string::size_type pos
= 0;
1586 // first convert all of the slashes
1587 while((pos
= ret
.find('/', pos
)) != kwsys_stl::string::npos
)
1592 // check for really small paths
1597 // now clean up a bit and remove double slashes
1598 // Only if it is not the first position in the path which is a network
1600 pos
= 1; // start at position 1
1603 pos
= 2; // if the string is already quoted then start at 2
1609 while((pos
= ret
.find("\\\\", pos
)) != kwsys_stl::string::npos
)
1613 // now double quote the path if it has spaces in it
1614 // and is not already double quoted
1615 if(ret
.find(' ') != kwsys_stl::string::npos
1618 ret
.insert(static_cast<kwsys_stl::string::size_type
>(0),
1619 static_cast<kwsys_stl::string::size_type
>(1), '\"');
1620 ret
.append(1, '\"');
1625 bool SystemTools::CopyFileIfDifferent(const char* source
,
1626 const char* destination
,
1627 bool copyPermissions
)
1629 // special check for a destination that is a directory
1630 // FilesDiffer does not handle file to directory compare
1631 if(SystemTools::FileIsDirectory(destination
))
1633 kwsys_stl::string new_destination
= destination
;
1634 SystemTools::ConvertToUnixSlashes(new_destination
);
1635 new_destination
+= '/';
1636 kwsys_stl::string source_name
= source
;
1637 new_destination
+= SystemTools::GetFilenameName(source_name
);
1638 if(SystemTools::FilesDiffer(source
, new_destination
.c_str()))
1640 return SystemTools::CopyFileAlways(source
, destination
,
1645 // the files are the same so the copy is done return
1650 // source and destination are files so do a copy if they
1652 if(SystemTools::FilesDiffer(source
, destination
))
1654 return SystemTools::CopyFileAlways(source
, destination
, copyPermissions
);
1656 // at this point the files must be the same so return true
1660 #define KWSYS_ST_BUFFER 4096
1662 bool SystemTools::FilesDiffer(const char* source
,
1663 const char* destination
)
1665 struct stat statSource
;
1666 if (stat(source
, &statSource
) != 0)
1671 struct stat statDestination
;
1672 if (stat(destination
, &statDestination
) != 0)
1677 if(statSource
.st_size
!= statDestination
.st_size
)
1682 if(statSource
.st_size
== 0)
1687 #if defined(_WIN32) || defined(__CYGWIN__)
1688 kwsys_ios::ifstream
finSource(source
, (kwsys_ios::ios::binary
|
1689 kwsys_ios::ios::in
));
1690 kwsys_ios::ifstream
finDestination(destination
, (kwsys_ios::ios::binary
|
1691 kwsys_ios::ios::in
));
1693 kwsys_ios::ifstream
finSource(source
);
1694 kwsys_ios::ifstream
finDestination(destination
);
1696 if(!finSource
|| !finDestination
)
1701 // Compare the files a block at a time.
1702 char source_buf
[KWSYS_ST_BUFFER
];
1703 char dest_buf
[KWSYS_ST_BUFFER
];
1704 off_t nleft
= statSource
.st_size
;
1707 // Read a block from each file.
1708 kwsys_ios::streamsize nnext
= (nleft
> KWSYS_ST_BUFFER
)? KWSYS_ST_BUFFER
: static_cast<kwsys_ios::streamsize
>(nleft
);
1709 finSource
.read(source_buf
, nnext
);
1710 finDestination
.read(dest_buf
, nnext
);
1712 // If either failed to read assume they are different.
1713 if(static_cast<kwsys_ios::streamsize
>(finSource
.gcount()) != nnext
||
1714 static_cast<kwsys_ios::streamsize
>(finDestination
.gcount()) != nnext
)
1719 // If this block differs the file differs.
1720 if(memcmp(static_cast<const void*>(source_buf
),
1721 static_cast<const void*>(dest_buf
),
1722 static_cast<size_t>(nnext
)) != 0)
1727 // Update the byte count remaining.
1731 // No differences found.
1736 //----------------------------------------------------------------------------
1738 * Copy a file named by "source" to the file named by "destination".
1740 bool SystemTools::CopyFileAlways(const char* source
, const char* destination
,
1741 bool copyPermissions
)
1743 // If files are the same do not copy
1744 if ( SystemTools::SameFile(source
, destination
) )
1749 bool perms
= SystemTools::GetPermissions(source
, perm
);
1751 const int bufferSize
= 4096;
1752 char buffer
[bufferSize
];
1754 // If destination is a directory, try to create a file with the same
1755 // name as the source in that directory.
1757 kwsys_stl::string new_destination
;
1758 if(SystemTools::FileExists(destination
) &&
1759 SystemTools::FileIsDirectory(destination
))
1761 new_destination
= destination
;
1762 SystemTools::ConvertToUnixSlashes(new_destination
);
1763 new_destination
+= '/';
1764 kwsys_stl::string source_name
= source
;
1765 new_destination
+= SystemTools::GetFilenameName(source_name
);
1766 destination
= new_destination
.c_str();
1769 // Create destination directory
1771 kwsys_stl::string destination_dir
= destination
;
1772 destination_dir
= SystemTools::GetFilenamePath(destination_dir
);
1773 SystemTools::MakeDirectory(destination_dir
.c_str());
1777 #if defined(_WIN32) || defined(__CYGWIN__)
1778 kwsys_ios::ifstream
fin(source
,
1779 kwsys_ios::ios::binary
| kwsys_ios::ios::in
);
1781 kwsys_ios::ifstream
fin(source
);
1788 // try and remove the destination file so that read only destination files
1789 // can be written to.
1790 // If the remove fails continue so that files in read only directories
1791 // that do not allow file removal can be modified.
1792 SystemTools::RemoveFile(destination
);
1794 #if defined(_WIN32) || defined(__CYGWIN__)
1795 kwsys_ios::ofstream
fout(destination
,
1796 kwsys_ios::ios::binary
| kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1798 kwsys_ios::ofstream
fout(destination
,
1799 kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1806 // This copy loop is very sensitive on certain platforms with
1807 // slightly broken stream libraries (like HPUX). Normally, it is
1808 // incorrect to not check the error condition on the fin.read()
1809 // before using the data, but the fin.gcount() will be zero if an
1810 // error occurred. Therefore, the loop should be safe everywhere.
1813 fin
.read(buffer
, bufferSize
);
1816 fout
.write(buffer
, fin
.gcount());
1820 // Make sure the operating system has finished writing the file
1821 // before closing it. This will ensure the file is finished before
1829 struct stat statSource
, statDestination
;
1830 statSource
.st_size
= 12345;
1831 statDestination
.st_size
= 12345;
1832 if(stat(source
, &statSource
) != 0)
1836 else if(stat(destination
, &statDestination
) != 0)
1840 else if(statSource
.st_size
!= statDestination
.st_size
)
1844 if ( copyPermissions
&& perms
)
1846 if ( !SystemTools::SetPermissions(destination
, perm
) )
1854 //----------------------------------------------------------------------------
1855 bool SystemTools::CopyAFile(const char* source
, const char* destination
,
1856 bool always
, bool copyPermissions
)
1860 return SystemTools::CopyFileAlways(source
, destination
, copyPermissions
);
1864 return SystemTools::CopyFileIfDifferent(source
, destination
, copyPermissions
);
1869 * Copy a directory content from "source" directory to the directory named by
1872 bool SystemTools::CopyADirectory(const char* source
, const char* destination
,
1873 bool always
, bool copyPermissions
)
1878 if ( !SystemTools::MakeDirectory(destination
) )
1882 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
1884 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
1885 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
1887 kwsys_stl::string fullPath
= source
;
1889 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1890 if(SystemTools::FileIsDirectory(fullPath
.c_str()))
1892 kwsys_stl::string fullDestPath
= destination
;
1893 fullDestPath
+= "/";
1894 fullDestPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1895 if (!SystemTools::CopyADirectory(fullPath
.c_str(),
1896 fullDestPath
.c_str(),
1905 if(!SystemTools::CopyAFile(fullPath
.c_str(), destination
, always
,
1918 // return size of file; also returns zero if no file exists
1919 unsigned long SystemTools::FileLength(const char* filename
)
1922 if (stat(filename
, &fs
) != 0)
1928 return static_cast<unsigned long>(fs
.st_size
);
1932 int SystemTools::Strucmp(const char *s1
, const char *s2
)
1934 // lifted from Graphvis http://www.graphviz.org
1935 while ((*s1
!= '\0')
1936 && (tolower(*s1
) == tolower(*s2
)))
1942 return tolower(*s1
) - tolower(*s2
);
1945 // return file's modified time
1946 long int SystemTools::ModifiedTime(const char* filename
)
1949 if (stat(filename
, &fs
) != 0)
1955 return static_cast<long int>(fs
.st_mtime
);
1959 // return file's creation time
1960 long int SystemTools::CreationTime(const char* filename
)
1963 if (stat(filename
, &fs
) != 0)
1969 return fs
.st_ctime
>= 0 ? static_cast<long int>(fs
.st_ctime
) : 0;
1973 bool SystemTools::ConvertDateMacroString(const char *str
, time_t *tmt
)
1975 if (!str
|| !tmt
|| strlen(str
) > 11)
1983 // The compilation date of the current source file. The date is a string
1984 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
1985 // dates generated by the library function asctime declared in TIME.H.
1987 // index: 012345678901
1988 // format: Mmm dd yyyy
1989 // example: Dec 19 2003
1991 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1994 strcpy(buffer
, str
);
1997 char *ptr
= strstr(month_names
, buffer
);
2003 int month
= static_cast<int>((ptr
- month_names
) / 3);
2004 int day
= atoi(buffer
+ 4);
2005 int year
= atoi(buffer
+ 7);
2014 tmt2
.tm_mon
= month
;
2015 tmt2
.tm_year
= year
- 1900;
2017 *tmt
= mktime(&tmt2
);
2021 bool SystemTools::ConvertTimeStampMacroString(const char *str
, time_t *tmt
)
2023 if (!str
|| !tmt
|| strlen(str
) > 26)
2031 // The date and time of the last modification of the current source file,
2032 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
2033 /// where Ddd is the abbreviated day of the week and Date is an integer
2036 // index: 0123456789
2039 // format: Ddd Mmm Date hh:mm:ss yyyy
2040 // example: Fri Dec 19 14:34:58 2003
2042 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
2045 strcpy(buffer
, str
);
2048 char *ptr
= strstr(month_names
, buffer
+ 4);
2054 int month
= static_cast<int>((ptr
- month_names
) / 3);
2055 int day
= atoi(buffer
+ 8);
2056 int hour
= atoi(buffer
+ 11);
2057 int min
= atoi(buffer
+ 14);
2058 int sec
= atoi(buffer
+ 17);
2059 int year
= atoi(buffer
+ 20);
2062 tmt2
.tm_hour
= hour
;
2068 tmt2
.tm_mon
= month
;
2069 tmt2
.tm_year
= year
- 1900;
2071 *tmt
= mktime(&tmt2
);
2075 kwsys_stl::string
SystemTools::GetLastSystemError()
2081 bool SystemTools::RemoveFile(const char* source
)
2085 if ( !SystemTools::GetPermissions(source
, mode
) )
2089 /* Win32 unlink is stupid --- it fails if the file is read-only */
2090 SystemTools::SetPermissions(source
, S_IWRITE
);
2092 bool res
= unlink(source
) != 0 ? false : true;
2096 SystemTools::SetPermissions(source
, mode
);
2102 bool SystemTools::RemoveADirectory(const char* source
)
2107 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
2109 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
2110 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
2112 kwsys_stl::string fullPath
= source
;
2114 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
2115 if(SystemTools::FileIsDirectory(fullPath
.c_str()) &&
2116 !SystemTools::FileIsSymlink(fullPath
.c_str()))
2118 if (!SystemTools::RemoveADirectory(fullPath
.c_str()))
2125 if(!SystemTools::RemoveFile(fullPath
.c_str()))
2133 return (Rmdir(source
) == 0);
2138 size_t SystemTools::GetMaximumFilePathLength()
2140 return KWSYS_SYSTEMTOOLS_MAXPATH
;
2144 * Find the file the given name. Searches the given path and then
2145 * the system search path. Returns the full path to the file if it is
2146 * found. Otherwise, the empty string is returned.
2148 kwsys_stl::string SystemTools
2149 ::FindName(const char* name
,
2150 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2151 bool no_system_path
)
2153 // Add the system search path to our path first
2154 kwsys_stl::vector
<kwsys_stl::string
> path
;
2155 if (!no_system_path
)
2157 SystemTools::GetPath(path
, "CMAKE_FILE_PATH");
2158 SystemTools::GetPath(path
);
2160 // now add the additional paths
2162 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= userPaths
.begin();
2163 i
!= userPaths
.end(); ++i
)
2168 // Add a trailing slash to all paths to aid the search process.
2170 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
2171 i
!= path
.end(); ++i
)
2173 kwsys_stl::string
& p
= *i
;
2174 if(p
.empty() || p
[p
.size()-1] != '/')
2180 // now look for the file
2181 kwsys_stl::string tryPath
;
2182 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
2183 p
!= path
.end(); ++p
)
2187 if(SystemTools::FileExists(tryPath
.c_str()))
2192 // Couldn't find the file.
2197 * Find the file the given name. Searches the given path and then
2198 * the system search path. Returns the full path to the file if it is
2199 * found. Otherwise, the empty string is returned.
2201 kwsys_stl::string SystemTools
2202 ::FindFile(const char* name
,
2203 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2204 bool no_system_path
)
2206 kwsys_stl::string tryPath
= SystemTools::FindName(name
, userPaths
, no_system_path
);
2207 if(tryPath
!= "" && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2209 return SystemTools::CollapseFullPath(tryPath
.c_str());
2211 // Couldn't find the file.
2216 * Find the directory the given name. Searches the given path and then
2217 * the system search path. Returns the full path to the directory if it is
2218 * found. Otherwise, the empty string is returned.
2220 kwsys_stl::string SystemTools
2221 ::FindDirectory(const char* name
,
2222 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2223 bool no_system_path
)
2225 kwsys_stl::string tryPath
= SystemTools::FindName(name
, userPaths
, no_system_path
);
2226 if(tryPath
!= "" && SystemTools::FileIsDirectory(tryPath
.c_str()))
2228 return SystemTools::CollapseFullPath(tryPath
.c_str());
2230 // Couldn't find the file.
2235 * Find the executable with the given name. Searches the given path and then
2236 * the system search path. Returns the full path to the executable if it is
2237 * found. Otherwise, the empty string is returned.
2239 kwsys_stl::string
SystemTools::FindProgram(
2241 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
2242 bool no_system_path
)
2244 if(!nameIn
|| !*nameIn
)
2248 kwsys_stl::string name
= nameIn
;
2249 kwsys_stl::vector
<kwsys_stl::string
> extensions
;
2250 #if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
2251 bool hasExtension
= false;
2252 // check to see if the name already has a .xxx at
2254 if(name
.size() > 3 && name
[name
.size()-4] == '.')
2256 hasExtension
= true;
2258 // on windows try .com then .exe
2261 extensions
.push_back(".com");
2262 extensions
.push_back(".exe");
2265 kwsys_stl::string tryPath
;
2267 // first try with extensions if the os supports them
2268 if(extensions
.size())
2270 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
=
2271 extensions
.begin(); i
!= extensions
.end(); ++i
)
2275 if(SystemTools::FileExists(tryPath
.c_str()) &&
2276 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2278 return SystemTools::CollapseFullPath(tryPath
.c_str());
2282 // now try just the name
2284 if(SystemTools::FileExists(tryPath
.c_str()) &&
2285 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2287 return SystemTools::CollapseFullPath(tryPath
.c_str());
2289 // now construct the path
2290 kwsys_stl::vector
<kwsys_stl::string
> path
;
2291 // Add the system search path to our path.
2292 if (!no_system_path
)
2294 SystemTools::GetPath(path
);
2296 // now add the additional paths
2298 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
=
2299 userPaths
.begin(); i
!= userPaths
.end(); ++i
)
2304 // Add a trailing slash to all paths to aid the search process.
2306 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
2307 i
!= path
.end(); ++i
)
2309 kwsys_stl::string
& p
= *i
;
2310 if(p
.empty() || p
[p
.size()-1] != '/')
2317 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator p
= path
.begin();
2318 p
!= path
.end(); ++p
)
2321 // Remove double quotes from the path on windows
2322 SystemTools::ReplaceString(*p
, "\"", "");
2324 // first try with extensions
2325 if(extensions
.size())
2327 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator ext
2328 = extensions
.begin(); ext
!= extensions
.end(); ++ext
)
2333 if(SystemTools::FileExists(tryPath
.c_str()) &&
2334 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2336 return SystemTools::CollapseFullPath(tryPath
.c_str());
2340 // now try it without them
2343 if(SystemTools::FileExists(tryPath
.c_str()) &&
2344 !SystemTools::FileIsDirectory(tryPath
.c_str()))
2346 return SystemTools::CollapseFullPath(tryPath
.c_str());
2349 // Couldn't find the program.
2353 kwsys_stl::string
SystemTools::FindProgram(
2354 const kwsys_stl::vector
<kwsys_stl::string
>& names
,
2355 const kwsys_stl::vector
<kwsys_stl::string
>& path
,
2358 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator it
= names
.begin();
2359 it
!= names
.end() ; ++it
)
2361 // Try to find the program.
2362 kwsys_stl::string result
= SystemTools::FindProgram(it
->c_str(),
2365 if ( !result
.empty() )
2374 * Find the library with the given name. Searches the given path and then
2375 * the system search path. Returns the full path to the library if it is
2376 * found. Otherwise, the empty string is returned.
2378 kwsys_stl::string SystemTools
2379 ::FindLibrary(const char* name
,
2380 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
)
2382 // See if the executable exists as written.
2383 if(SystemTools::FileExists(name
) &&
2384 !SystemTools::FileIsDirectory(name
))
2386 return SystemTools::CollapseFullPath(name
);
2389 // Add the system search path to our path.
2390 kwsys_stl::vector
<kwsys_stl::string
> path
;
2391 SystemTools::GetPath(path
);
2392 // now add the additional paths
2394 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= userPaths
.begin();
2395 i
!= userPaths
.end(); ++i
)
2400 // Add a trailing slash to all paths to aid the search process.
2402 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
2403 i
!= path
.end(); ++i
)
2405 kwsys_stl::string
& p
= *i
;
2406 if(p
.empty() || p
[p
.size()-1] != '/')
2412 kwsys_stl::string tryPath
;
2413 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
2414 p
!= path
.end(); ++p
)
2416 #if defined(__APPLE__)
2419 tryPath
+= ".framework";
2420 if(SystemTools::FileExists(tryPath
.c_str())
2421 && SystemTools::FileIsDirectory(tryPath
.c_str()))
2423 return SystemTools::CollapseFullPath(tryPath
.c_str());
2426 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
2430 if(SystemTools::FileExists(tryPath
.c_str())
2431 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2433 return SystemTools::CollapseFullPath(tryPath
.c_str());
2440 if(SystemTools::FileExists(tryPath
.c_str())
2441 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2443 return SystemTools::CollapseFullPath(tryPath
.c_str());
2449 if(SystemTools::FileExists(tryPath
.c_str())
2450 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2452 return SystemTools::CollapseFullPath(tryPath
.c_str());
2458 if(SystemTools::FileExists(tryPath
.c_str())
2459 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2461 return SystemTools::CollapseFullPath(tryPath
.c_str());
2466 tryPath
+= ".dylib";
2467 if(SystemTools::FileExists(tryPath
.c_str())
2468 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2470 return SystemTools::CollapseFullPath(tryPath
.c_str());
2476 if(SystemTools::FileExists(tryPath
.c_str())
2477 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2479 return SystemTools::CollapseFullPath(tryPath
.c_str());
2484 // Couldn't find the library.
2488 kwsys_stl::string
SystemTools::GetRealPath(const char* path
)
2490 kwsys_stl::string ret
;
2491 Realpath(path
, ret
);
2495 bool SystemTools::FileIsDirectory(const char* name
)
2497 // Remove any trailing slash from the name.
2498 char buffer
[KWSYS_SYSTEMTOOLS_MAXPATH
];
2499 size_t last
= strlen(name
)-1;
2500 if(last
> 0 && (name
[last
] == '/' || name
[last
] == '\\')
2501 && strcmp(name
, "/") !=0)
2503 memcpy(buffer
, name
, last
);
2508 // Now check the file node type.
2510 if(stat(name
, &fs
) == 0)
2512 #if defined( _WIN32 )
2513 return ((fs
.st_mode
& _S_IFDIR
) != 0);
2515 return S_ISDIR(fs
.st_mode
);
2524 bool SystemTools::FileIsSymlink(const char* name
)
2526 #if defined( _WIN32 )
2531 if(lstat(name
, &fs
) == 0)
2533 return S_ISLNK(fs
.st_mode
);
2542 #if defined(_WIN32) && !defined(__CYGWIN__)
2543 bool SystemTools::CreateSymlink(const char*, const char*)
2548 bool SystemTools::CreateSymlink(const char* origName
, const char* newName
)
2550 return symlink(origName
, newName
) >= 0;
2554 #if defined(_WIN32) && !defined(__CYGWIN__)
2555 bool SystemTools::ReadSymlink(const char*, kwsys_stl::string
&)
2560 bool SystemTools::ReadSymlink(const char* newName
,
2561 kwsys_stl::string
& origName
)
2563 char buf
[KWSYS_SYSTEMTOOLS_MAXPATH
+1];
2565 static_cast<int>(readlink(newName
, buf
, KWSYS_SYSTEMTOOLS_MAXPATH
));
2568 // Add null-terminator.
2580 int SystemTools::ChangeDirectory(const char *dir
)
2585 kwsys_stl::string
SystemTools::GetCurrentWorkingDirectory(bool collapse
)
2588 const char* cwd
= Getcwd(buf
, 2048);
2589 kwsys_stl::string path
;
2596 return SystemTools::CollapseFullPath(path
.c_str());
2601 kwsys_stl::string
SystemTools::GetProgramPath(const char* in_name
)
2603 kwsys_stl::string dir
, file
;
2604 SystemTools::SplitProgramPath(in_name
, dir
, file
);
2608 bool SystemTools::SplitProgramPath(const char* in_name
,
2609 kwsys_stl::string
& dir
,
2610 kwsys_stl::string
& file
,
2615 SystemTools::ConvertToUnixSlashes(dir
);
2617 if(!SystemTools::FileIsDirectory(dir
.c_str()))
2619 kwsys_stl::string::size_type slashPos
= dir
.rfind("/");
2620 if(slashPos
!= kwsys_stl::string::npos
)
2622 file
= dir
.substr(slashPos
+1);
2623 dir
= dir
.substr(0, slashPos
);
2631 if(!(dir
== "") && !SystemTools::FileIsDirectory(dir
.c_str()))
2633 kwsys_stl::string oldDir
= in_name
;
2634 SystemTools::ConvertToUnixSlashes(oldDir
);
2641 bool SystemTools::FindProgramPath(const char* argv0
,
2642 kwsys_stl::string
& pathOut
,
2643 kwsys_stl::string
& errorMsg
,
2644 const char* exeName
,
2645 const char* buildDir
,
2646 const char* installPrefix
)
2648 kwsys_stl::vector
<kwsys_stl::string
> failures
;
2649 kwsys_stl::string self
= argv0
? argv0
: "";
2650 failures
.push_back(self
);
2651 SystemTools::ConvertToUnixSlashes(self
);
2652 self
= SystemTools::FindProgram(self
.c_str());
2653 if(!SystemTools::FileExists(self
.c_str()))
2657 kwsys_stl::string intdir
= ".";
2659 intdir
= CMAKE_INTDIR
;
2666 self
+= SystemTools::GetExecutableExtension();
2671 if(!SystemTools::FileExists(self
.c_str()))
2673 failures
.push_back(self
);
2674 self
= installPrefix
;
2679 if(!SystemTools::FileExists(self
.c_str()))
2681 failures
.push_back(self
);
2682 kwsys_ios::ostringstream msg
;
2683 msg
<< "Can not find the command line program ";
2691 msg
<< " argv[0] = \"" << argv0
<< "\"\n";
2693 msg
<< " Attempted paths:\n";
2694 kwsys_stl::vector
<kwsys_stl::string
>::iterator i
;
2695 for(i
=failures
.begin(); i
!= failures
.end(); ++i
)
2697 msg
<< " \"" << i
->c_str() << "\"\n";
2699 errorMsg
= msg
.str();
2707 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_relative
)
2709 return SystemTools::CollapseFullPath(in_relative
, 0);
2712 void SystemTools::AddTranslationPath(const char * a
, const char * b
)
2714 kwsys_stl::string path_a
= a
;
2715 kwsys_stl::string path_b
= b
;
2716 SystemTools::ConvertToUnixSlashes(path_a
);
2717 SystemTools::ConvertToUnixSlashes(path_b
);
2718 // First check this is a directory path, since we don't want the table to
2720 if( SystemTools::FileIsDirectory( path_a
.c_str() ) )
2722 // Make sure the path is a full path and does not contain no '..'
2723 // Ken--the following code is incorrect. .. can be in a valid path
2724 // for example /home/martink/MyHubba...Hubba/Src
2725 if( SystemTools::FileIsFullPath(path_b
.c_str()) && path_b
.find("..")
2726 == kwsys_stl::string::npos
)
2728 // Before inserting make sure path ends with '/'
2729 if(path_a
.size() && path_a
[path_a
.size() -1] != '/')
2733 if(path_b
.size() && path_b
[path_b
.size() -1] != '/')
2737 if( !(path_a
== path_b
) )
2739 SystemTools::TranslationMap
->insert(
2740 SystemToolsTranslationMap::value_type(path_a
, path_b
));
2746 void SystemTools::AddKeepPath(const char* dir
)
2748 kwsys_stl::string cdir
;
2749 Realpath(SystemTools::CollapseFullPath(dir
).c_str(), cdir
);
2750 SystemTools::AddTranslationPath(cdir
.c_str(), dir
);
2753 void SystemTools::CheckTranslationPath(kwsys_stl::string
& path
)
2755 // Do not translate paths that are too short to have meaningful
2762 // Always add a trailing slash before translation. It does not
2763 // matter if this adds an extra slash, but we do not want to
2764 // translate part of a directory (like the foo part of foo-dir).
2767 // In case a file was specified we still have to go through this:
2768 // Now convert any path found in the table back to the one desired:
2769 kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>::const_iterator it
;
2770 for(it
= SystemTools::TranslationMap
->begin();
2771 it
!= SystemTools::TranslationMap
->end();
2774 // We need to check of the path is a substring of the other path
2775 if(path
.find( it
->first
) == 0)
2777 path
= path
.replace( 0, it
->first
.size(), it
->second
);
2781 // Remove the trailing slash we added before.
2782 path
.erase(path
.end()-1, path
.end());
2786 SystemToolsAppendComponents(
2787 kwsys_stl::vector
<kwsys_stl::string
>& out_components
,
2788 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator first
,
2789 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator last
)
2791 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= first
;
2796 if(out_components
.begin() != out_components
.end())
2798 out_components
.erase(out_components
.end()-1, out_components
.end());
2801 else if(!(*i
== ".") && !(*i
== ""))
2803 out_components
.push_back(*i
);
2808 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_path
,
2809 const char* in_base
)
2811 // Collect the output path components.
2812 kwsys_stl::vector
<kwsys_stl::string
> out_components
;
2814 // Split the input path components.
2815 kwsys_stl::vector
<kwsys_stl::string
> path_components
;
2816 SystemTools::SplitPath(in_path
, path_components
);
2818 // If the input path is relative, start with a base path.
2819 if(path_components
[0].length() == 0)
2821 kwsys_stl::vector
<kwsys_stl::string
> base_components
;
2824 // Use the given base path.
2825 SystemTools::SplitPath(in_base
, base_components
);
2829 // Use the current working directory as a base path.
2831 if(const char* cwd
= Getcwd(buf
, 2048))
2833 SystemTools::SplitPath(cwd
, base_components
);
2841 // Append base path components to the output path.
2842 out_components
.push_back(base_components
[0]);
2843 SystemToolsAppendComponents(out_components
,
2844 base_components
.begin()+1,
2845 base_components
.end());
2848 // Append input path components to the output path.
2849 SystemToolsAppendComponents(out_components
,
2850 path_components
.begin(),
2851 path_components
.end());
2853 // Transform the path back to a string.
2854 kwsys_stl::string newPath
= SystemTools::JoinPath(out_components
);
2856 // Update the translation table with this potentially new path. I am not
2857 // sure why this line is here, it seems really questionable, but yet I
2858 // would put good money that if I remove it something will break, basically
2859 // from what I can see it created a mapping from the collapsed path, to be
2860 // replaced by the input path, which almost completely does the opposite of
2861 // this function, the only thing preventing this from happening a lot is
2862 // that if the in_path has a .. in it, then it is not added to the
2863 // translation table. So for most calls this either does nothing due to the
2864 // .. or it adds a translation between identical paths as nothing was
2865 // collapsed, so I am going to try to comment it out, and see what hits the
2866 // fan, hopefully quickly.
2867 // Commented out line below:
2868 //SystemTools::AddTranslationPath(newPath.c_str(), in_path);
2870 SystemTools::CheckTranslationPath(newPath
);
2872 newPath
= SystemTools::GetActualCaseForPath(newPath
.c_str());
2873 SystemTools::ConvertToUnixSlashes(newPath
);
2875 // Return the reconstructed path.
2879 // compute the relative path from here to there
2880 kwsys_stl::string
SystemTools::RelativePath(const char* local
, const char* remote
)
2882 if(!SystemTools::FileIsFullPath(local
))
2886 if(!SystemTools::FileIsFullPath(remote
))
2891 // split up both paths into arrays of strings using / as a separator
2892 kwsys_stl::vector
<kwsys::String
> localSplit
= SystemTools::SplitString(local
, '/', true);
2893 kwsys_stl::vector
<kwsys::String
> remoteSplit
= SystemTools::SplitString(remote
, '/', true);
2894 kwsys_stl::vector
<kwsys::String
> commonPath
; // store shared parts of path in this array
2895 kwsys_stl::vector
<kwsys::String
> finalPath
; // store the final relative path here
2896 // count up how many matching directory names there are from the start
2897 unsigned int sameCount
= 0;
2899 ((sameCount
<= (localSplit
.size()-1)) && (sameCount
<= (remoteSplit
.size()-1)))
2901 // for windows and apple do a case insensitive string compare
2902 #if defined(_WIN32) || defined(__APPLE__)
2903 SystemTools::Strucmp(localSplit
[sameCount
].c_str(),
2904 remoteSplit
[sameCount
].c_str()) == 0
2906 localSplit
[sameCount
] == remoteSplit
[sameCount
]
2910 // put the common parts of the path into the commonPath array
2911 commonPath
.push_back(localSplit
[sameCount
]);
2912 // erase the common parts of the path from the original path arrays
2913 localSplit
[sameCount
] = "";
2914 remoteSplit
[sameCount
] = "";
2918 // If there is nothing in common at all then just return the full
2919 // path. This is the case only on windows when the paths have
2920 // different drive letters. On unix two full paths always at least
2921 // have the root "/" in common so we will return a relative path
2922 // that passes through the root directory.
2928 // for each entry that is not common in the local path
2929 // add a ../ to the finalpath array, this gets us out of the local
2930 // path into the remote dir
2931 for(unsigned int i
= 0; i
< localSplit
.size(); ++i
)
2933 if(localSplit
[i
].size())
2935 finalPath
.push_back("../");
2938 // for each entry that is not common in the remote path add it
2939 // to the final path.
2940 for(kwsys_stl::vector
<String
>::iterator vit
= remoteSplit
.begin();
2941 vit
!= remoteSplit
.end(); ++vit
)
2945 finalPath
.push_back(*vit
);
2948 kwsys_stl::string relativePath
; // result string
2949 // now turn the array of directories into a unix path by puttint /
2950 // between each entry that does not already have one
2951 for(kwsys_stl::vector
<String
>::iterator vit1
= finalPath
.begin();
2952 vit1
!= finalPath
.end(); ++vit1
)
2954 if(relativePath
.size() && relativePath
[relativePath
.size()-1] != '/')
2956 relativePath
+= "/";
2958 relativePath
+= *vit1
;
2960 return relativePath
;
2963 // OK, some fun stuff to get the actual case of a given path.
2964 // Basically, you just need to call ShortPath, then GetLongPathName,
2965 // However, GetLongPathName is not implemented on windows NT and 95,
2966 // so we have to simulate it on those versions
2968 int OldWindowsGetLongPath(kwsys_stl::string
const& shortPath
,
2969 kwsys_stl::string
& longPath
)
2971 kwsys_stl::string::size_type iFound
= shortPath
.rfind('/');
2972 if (iFound
> 1 && iFound
!= shortPath
.npos
)
2974 // recurse to peel off components
2976 if (OldWindowsGetLongPath(shortPath
.substr(0, iFound
), longPath
) > 0)
2979 if (shortPath
[1] != '/')
2981 WIN32_FIND_DATA findData
;
2983 // append the long component name to the path
2985 if (INVALID_HANDLE_VALUE
!= ::FindFirstFile
2986 (shortPath
.c_str(), &findData
))
2988 longPath
+= findData
.cFileName
;
2992 // if FindFirstFile fails, return the error code
3002 longPath
= shortPath
;
3004 return (int)longPath
.size();
3008 int PortableGetLongPathName(const char* pathIn
,
3009 kwsys_stl::string
& longPath
)
3011 HMODULE lh
= LoadLibrary("Kernel32.dll");
3014 FARPROC proc
= GetProcAddress(lh
, "GetLongPathNameA");
3017 typedef DWORD (WINAPI
* GetLongFunctionPtr
) (LPCSTR
,LPSTR
,DWORD
);
3018 GetLongFunctionPtr func
= (GetLongFunctionPtr
)proc
;
3019 char buffer
[MAX_PATH
+1];
3020 int len
= (*func
)(pathIn
, buffer
, MAX_PATH
+1);
3021 if(len
== 0 || len
> MAX_PATH
+1)
3032 return OldWindowsGetLongPath(pathIn
, longPath
);
3037 //----------------------------------------------------------------------------
3038 kwsys_stl::string
SystemTools::GetActualCaseForPath(const char* p
)
3043 // Check to see if actual case has already been called
3044 // for this path, and the result is stored in the LongPathMap
3045 SystemToolsTranslationMap::iterator i
=
3046 SystemTools::LongPathMap
->find(p
);
3047 if(i
!= SystemTools::LongPathMap
->end())
3051 kwsys_stl::string shortPath
;
3052 if(!SystemTools::GetShortPath(p
, shortPath
))
3056 kwsys_stl::string longPath
;
3057 int len
= PortableGetLongPathName(shortPath
.c_str(), longPath
);
3058 if(len
== 0 || len
> MAX_PATH
+1)
3062 // Use original path if conversion back to a long path failed.
3063 if(longPath
== shortPath
)
3067 // make sure drive letter is always upper case
3068 if(longPath
.size() > 1 && longPath
[1] == ':')
3070 longPath
[0] = toupper(longPath
[0]);
3072 (*SystemTools::LongPathMap
)[p
] = longPath
;
3077 //----------------------------------------------------------------------------
3078 const char* SystemTools::SplitPathRootComponent(const char* p
,
3079 kwsys_stl::string
* root
)
3081 // Identify the root component.
3083 if((c
[0] == '/' && c
[1] == '/') || (c
[0] == '\\' && c
[1] == '\\'))
3092 else if(c
[0] == '/')
3101 else if(c
[0] && c
[1] == ':' && (c
[2] == '/' || c
[2] == '\\'))
3111 else if(c
[0] && c
[1] == ':')
3113 // Path relative to a windows drive working directory.
3121 else if(c
[0] == '~')
3123 // Home directory. The returned root should always have a
3124 // trailing slash so that appending components as
3125 // c[0]c[1]/c[2]/... works. The remaining path returned should
3126 // skip the first slash if it exists:
3128 // "~" : root = "~/" , return ""
3129 // "~/ : root = "~/" , return ""
3130 // "~/x : root = "~/" , return "x"
3131 // "~u" : root = "~u/", return ""
3132 // "~u/" : root = "~u/", return ""
3133 // "~u/x" : root = "~u/", return "x"
3135 while(c
[n
] && c
[n
] != '/')
3159 // Return the remaining path.
3163 //----------------------------------------------------------------------------
3164 void SystemTools::SplitPath(const char* p
,
3165 kwsys_stl::vector
<kwsys_stl::string
>& components
,
3166 bool expand_home_dir
)
3171 // Identify the root component.
3173 kwsys_stl::string root
;
3174 c
= SystemTools::SplitPathRootComponent(c
, &root
);
3176 // Expand home directory references if requested.
3177 if(expand_home_dir
&& !root
.empty() && root
[0] == '~')
3179 kwsys_stl::string homedir
;
3180 root
= root
.substr(0, root
.size()-1);
3181 if(root
.size() == 1)
3183 #if defined(_WIN32) && !defined(__CYGWIN__)
3184 if(const char* userp
= getenv("USERPROFILE"))
3190 if(const char* h
= getenv("HOME"))
3195 #ifdef HAVE_GETPWNAM
3196 else if(passwd
* pw
= getpwnam(root
.c_str()+1))
3200 homedir
= pw
->pw_dir
;
3204 if(!homedir
.empty() && (homedir
[homedir
.size()-1] == '/' ||
3205 homedir
[homedir
.size()-1] == '\\'))
3207 homedir
= homedir
.substr(0, homedir
.size()-1);
3209 SystemTools::SplitPath(homedir
.c_str(), components
);
3213 components
.push_back(root
);
3217 // Parse the remaining components.
3218 const char* first
= c
;
3219 const char* last
= first
;
3222 if(*last
== '/' || *last
== '\\')
3224 // End of a component. Save it.
3225 components
.push_back(
3226 kwsys_stl::string(first
,static_cast<kwsys_stl::string::size_type
>(
3232 // Save the last component unless there were no components.
3235 components
.push_back(
3236 kwsys_stl::string(first
,static_cast<kwsys_stl::string::size_type
>(
3241 //----------------------------------------------------------------------------
3243 SystemTools::JoinPath(const kwsys_stl::vector
<kwsys_stl::string
>& components
)
3245 return SystemTools::JoinPath(components
.begin(), components
.end());
3248 //----------------------------------------------------------------------------
3251 ::JoinPath(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator first
,
3252 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator last
)
3254 // Construct result in a single string.
3255 kwsys_stl::string result
;
3257 // The first two components do not add a slash.
3267 // All remaining components are always separated with a slash.
3268 while(first
!= last
)
3274 // Return the concatenated result.
3278 //----------------------------------------------------------------------------
3279 bool SystemTools::ComparePath(const char* c1
, const char* c2
)
3281 #if defined(_WIN32) || defined(__APPLE__)
3283 return _stricmp(c1
, c2
) == 0;
3284 # elif defined(__APPLE__) || defined(__GNUC__)
3285 return strcasecmp(c1
, c2
) == 0;
3287 return SystemTools::Strucmp(c1
, c2
) == 0;
3290 return strcmp(c1
, c2
) == 0;
3294 //----------------------------------------------------------------------------
3295 bool SystemTools::Split(const char* str
, kwsys_stl::vector
<kwsys_stl::string
>& lines
, char separator
)
3297 kwsys_stl::string
data(str
);
3298 kwsys_stl::string::size_type lpos
= 0;
3299 while(lpos
< data
.length())
3301 kwsys_stl::string::size_type rpos
= data
.find_first_of(separator
, lpos
);
3302 if(rpos
== kwsys_stl::string::npos
)
3304 // Line ends at end of string without a newline.
3305 lines
.push_back(data
.substr(lpos
));
3310 // Line ends in a "\n", remove the character.
3311 lines
.push_back(data
.substr(lpos
, rpos
-lpos
));
3318 //----------------------------------------------------------------------------
3319 bool SystemTools::Split(const char* str
, kwsys_stl::vector
<kwsys_stl::string
>& lines
)
3321 kwsys_stl::string
data(str
);
3322 kwsys_stl::string::size_type lpos
= 0;
3323 while(lpos
< data
.length())
3325 kwsys_stl::string::size_type rpos
= data
.find_first_of("\n", lpos
);
3326 if(rpos
== kwsys_stl::string::npos
)
3328 // Line ends at end of string without a newline.
3329 lines
.push_back(data
.substr(lpos
));
3332 if((rpos
> lpos
) && (data
[rpos
-1] == '\r'))
3334 // Line ends in a "\r\n" pair, remove both characters.
3335 lines
.push_back(data
.substr(lpos
, (rpos
-1)-lpos
));
3339 // Line ends in a "\n", remove the character.
3340 lines
.push_back(data
.substr(lpos
, rpos
-lpos
));
3348 * Return path of a full filename (no trailing slashes).
3349 * Warning: returned path is converted to Unix slashes format.
3351 kwsys_stl::string
SystemTools::GetFilenamePath(const kwsys_stl::string
& filename
)
3353 kwsys_stl::string fn
= filename
;
3354 SystemTools::ConvertToUnixSlashes(fn
);
3356 kwsys_stl::string::size_type slash_pos
= fn
.rfind("/");
3357 if(slash_pos
!= kwsys_stl::string::npos
)
3359 kwsys_stl::string ret
= fn
.substr(0, slash_pos
);
3360 if(ret
.size() == 2 && ret
[1] == ':')
3378 * Return file name of a full filename (i.e. file name without path).
3380 kwsys_stl::string
SystemTools::GetFilenameName(const kwsys_stl::string
& filename
)
3383 kwsys_stl::string::size_type slash_pos
= filename
.find_last_of("/\\");
3385 kwsys_stl::string::size_type slash_pos
= filename
.find_last_of("/");
3387 if(slash_pos
!= kwsys_stl::string::npos
)
3389 return filename
.substr(slash_pos
+ 1);
3399 * Return file extension of a full filename (dot included).
3400 * Warning: this is the longest extension (for example: .tar.gz)
3402 kwsys_stl::string
SystemTools::GetFilenameExtension(const kwsys_stl::string
& filename
)
3404 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3405 kwsys_stl::string::size_type dot_pos
= name
.find(".");
3406 if(dot_pos
!= kwsys_stl::string::npos
)
3408 return name
.substr(dot_pos
);
3417 * Return file extension of a full filename (dot included).
3418 * Warning: this is the shortest extension (for example: .gz of .tar.gz)
3420 kwsys_stl::string
SystemTools::GetFilenameLastExtension(const kwsys_stl::string
& filename
)
3422 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3423 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
3424 if(dot_pos
!= kwsys_stl::string::npos
)
3426 return name
.substr(dot_pos
);
3435 * Return file name without extension of a full filename (i.e. without path).
3436 * Warning: it considers the longest extension (for example: .tar.gz)
3438 kwsys_stl::string
SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string
& filename
)
3440 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3441 kwsys_stl::string::size_type dot_pos
= name
.find(".");
3442 if(dot_pos
!= kwsys_stl::string::npos
)
3444 return name
.substr(0, dot_pos
);
3454 * Return file name without extension of a full filename (i.e. without path).
3455 * Warning: it considers the last extension (for example: removes .gz
3459 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string
& filename
)
3461 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
3462 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
3463 if(dot_pos
!= kwsys_stl::string::npos
)
3465 return name
.substr(0, dot_pos
);
3473 bool SystemTools::FileHasSignature(const char *filename
,
3474 const char *signature
,
3477 if (!filename
|| !signature
)
3483 fp
= fopen(filename
, "rb");
3489 fseek(fp
, offset
, SEEK_SET
);
3492 size_t signature_len
= strlen(signature
);
3493 char *buffer
= new char [signature_len
];
3495 if (fread(buffer
, 1, signature_len
, fp
) == signature_len
)
3497 res
= (!strncmp(buffer
, signature
, signature_len
) ? true : false);
3506 SystemTools::FileTypeEnum
3507 SystemTools::DetectFileType(const char *filename
,
3508 unsigned long length
,
3511 if (!filename
|| percent_bin
< 0)
3513 return SystemTools::FileTypeUnknown
;
3517 fp
= fopen(filename
, "rb");
3520 return SystemTools::FileTypeUnknown
;
3523 // Allocate buffer and read bytes
3525 unsigned char *buffer
= new unsigned char [length
];
3526 size_t read_length
= fread(buffer
, 1, length
, fp
);
3528 if (read_length
== 0)
3530 return SystemTools::FileTypeUnknown
;
3533 // Loop over contents and count
3535 size_t text_count
= 0;
3537 const unsigned char *ptr
= buffer
;
3538 const unsigned char *buffer_end
= buffer
+ read_length
;
3540 while (ptr
!= buffer_end
)
3542 if ((*ptr
>= 0x20 && *ptr
<= 0x7F) ||
3554 double current_percent_bin
=
3555 (static_cast<double>(read_length
- text_count
) /
3556 static_cast<double>(read_length
));
3558 if (current_percent_bin
>= percent_bin
)
3560 return SystemTools::FileTypeBinary
;
3563 return SystemTools::FileTypeText
;
3566 bool SystemTools::LocateFileInDir(const char *filename
,
3568 kwsys_stl::string
& filename_found
,
3569 int try_filename_dirs
)
3571 if (!filename
|| !dir
)
3576 // Get the basename of 'filename'
3578 kwsys_stl::string filename_base
= SystemTools::GetFilenameName(filename
);
3580 // Check if 'dir' is really a directory
3581 // If win32 and matches something like C:, accept it as a dir
3583 kwsys_stl::string real_dir
;
3584 if (!SystemTools::FileIsDirectory(dir
))
3586 #if defined( _WIN32 )
3587 size_t dir_len
= strlen(dir
);
3588 if (dir_len
< 2 || dir
[dir_len
- 1] != ':')
3591 real_dir
= SystemTools::GetFilenamePath(dir
);
3592 dir
= real_dir
.c_str();
3593 #if defined( _WIN32 )
3598 // Try to find the file in 'dir'
3601 if (filename_base
.size() && dir
)
3603 size_t dir_len
= strlen(dir
);
3605 (dir_len
&& dir
[dir_len
- 1] != '/' && dir
[dir_len
- 1] != '\\');
3607 kwsys_stl::string temp
= dir
;
3612 temp
+= filename_base
;
3614 if (SystemTools::FileExists(temp
.c_str()))
3617 filename_found
= temp
;
3620 // If not found, we can try harder by appending part of the file to
3621 // to the directory to look inside.
3622 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
3623 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
3625 else if (try_filename_dirs
)
3627 kwsys_stl::string
filename_dir(filename
);
3628 kwsys_stl::string filename_dir_base
;
3629 kwsys_stl::string filename_dir_bases
;
3632 filename_dir
= SystemTools::GetFilenamePath(filename_dir
);
3633 filename_dir_base
= SystemTools::GetFilenameName(filename_dir
);
3634 #if defined( _WIN32 )
3635 if (!filename_dir_base
.size() ||
3636 filename_dir_base
[filename_dir_base
.size() - 1] == ':')
3638 if (!filename_dir_base
.size())
3644 filename_dir_bases
= filename_dir_base
+ "/" + filename_dir_bases
;
3651 temp
+= filename_dir_bases
;
3653 res
= SystemTools::LocateFileInDir(
3654 filename_base
.c_str(), temp
.c_str(), filename_found
, 0);
3656 } while (!res
&& filename_dir_base
.size());
3663 bool SystemTools::FileIsFullPath(const char* in_name
)
3665 kwsys_stl::string name
= in_name
;
3666 #if defined(_WIN32) || defined(__CYGWIN__)
3667 // On Windows, the name must be at least two characters long.
3668 if(name
.length() < 2)
3681 // On UNIX, the name must be at least one character long.
3682 if(name
.length() < 1)
3687 #if !defined(_WIN32)
3693 // On UNIX, the name must begin in a '/'.
3694 // On Windows, if the name begins in a '/', then it is a full
3703 bool SystemTools::GetShortPath(const char* path
, kwsys_stl::string
& shortPath
)
3705 #if defined(WIN32) && !defined(__CYGWIN__)
3706 const int size
= int(strlen(path
)) +1; // size of return
3707 char *buffer
= new char[size
]; // create a buffer
3708 char *tempPath
= new char[size
]; // create a buffer
3711 // if the path passed in has quotes around it, first remove the quotes
3712 if (path
[0] == '"' && path
[strlen(path
)-1] == '"')
3714 strcpy(tempPath
,path
+1);
3715 tempPath
[strlen(tempPath
)-1] = '\0';
3719 strcpy(tempPath
,path
);
3723 ret
= GetShortPathName(tempPath
, buffer
, size
);
3725 if(buffer
[0] == 0 || ret
> size
)
3744 void SystemTools::SplitProgramFromArgs(const char* path
,
3745 kwsys_stl::string
& program
, kwsys_stl::string
& args
)
3747 // see if this is a full path to a program
3748 // if so then set program to path and args to nothing
3749 if(SystemTools::FileExists(path
))
3755 // Try to find the program in the path, note the program
3756 // may have spaces in its name so we have to look for it
3757 kwsys_stl::vector
<kwsys_stl::string
> e
;
3758 kwsys_stl::string findProg
= SystemTools::FindProgram(path
, e
);
3766 // Now try and peel off space separated chunks from the end of the string
3767 // so the largest path possible is found allowing for spaces in the path
3768 kwsys_stl::string dir
= path
;
3769 kwsys_stl::string::size_type spacePos
= dir
.rfind(' ');
3770 while(spacePos
!= kwsys_stl::string::npos
)
3772 kwsys_stl::string tryProg
= dir
.substr(0, spacePos
);
3773 // See if the file exists
3774 if(SystemTools::FileExists(tryProg
.c_str()))
3777 // remove trailing spaces from program
3778 kwsys_stl::string::size_type pos
= program
.size()-1;
3779 while(program
[pos
] == ' ')
3784 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
3787 // Now try and find the the program in the path
3788 findProg
= SystemTools::FindProgram(tryProg
.c_str(), e
);
3792 // remove trailing spaces from program
3793 kwsys_stl::string::size_type pos
= program
.size()-1;
3794 while(program
[pos
] == ' ')
3799 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
3802 // move past the space for the next search
3804 spacePos
= dir
.rfind(' ', spacePos
);
3811 kwsys_stl::string
SystemTools::GetCurrentDateTime(const char* format
)
3816 strftime(buf
, sizeof(buf
), format
, localtime(&t
));
3817 return kwsys_stl::string(buf
);
3820 kwsys_stl::string
SystemTools::MakeCindentifier(const char* s
)
3822 kwsys_stl::string
str(s
);
3823 if (str
.find_first_of("0123456789") == 0)
3828 kwsys_stl::string
permited_chars("_"
3829 "abcdefghijklmnopqrstuvwxyz"
3830 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3832 kwsys_stl::string::size_type pos
= 0;
3833 while ((pos
= str
.find_first_not_of(permited_chars
, pos
)) != kwsys_stl::string::npos
)
3840 // Due to a buggy stream library on the HP and another on Mac OS X, we
3841 // need this very carefully written version of getline. Returns true
3842 // if any data were read before the end-of-file was reached.
3843 bool SystemTools::GetLineFromStream(kwsys_ios::istream
& is
,
3844 kwsys_stl::string
& line
,
3845 bool* has_newline
/* = 0 */,
3846 long sizeLimit
/* = -1 */)
3848 const int bufferSize
= 1024;
3849 char buffer
[bufferSize
];
3850 bool haveData
= false;
3851 bool haveNewline
= false;
3853 // Start with an empty line.
3856 long leftToRead
= sizeLimit
;
3858 // If no characters are read from the stream, the end of file has
3859 // been reached. Clear the fail bit just before reading.
3860 while(!haveNewline
&&
3862 (is
.clear(is
.rdstate() & ~kwsys_ios::ios::failbit
),
3863 is
.getline(buffer
, bufferSize
), is
.gcount() > 0))
3865 // We have read at least one byte.
3868 // If newline character was read the gcount includes the character
3869 // but the buffer does not: the end of line has been reached.
3870 size_t length
= strlen(buffer
);
3871 if(length
< static_cast<size_t>(is
.gcount()))
3876 // Avoid storing a carriage return character.
3877 if(length
> 0 && buffer
[length
-1] == '\r')
3879 buffer
[length
-1] = 0;
3882 // if we read too much then truncate the buffer
3885 if (static_cast<long>(length
) > leftToRead
)
3887 buffer
[leftToRead
-1] = 0;
3892 leftToRead
-= static_cast<long>(length
);
3896 // Append the data read to the line.
3897 line
.append(buffer
);
3898 sizeLimit
= sizeLimit
- static_cast<long>(length
);
3901 // Return the results.
3904 *has_newline
= haveNewline
;
3909 int SystemTools::GetTerminalWidth()
3912 #ifdef HAVE_TTY_INFO
3914 char *columns
; /* Unix98 environment variable */
3915 if(ioctl(1, TIOCGWINSZ
, &ws
) != -1 && ws
.ws_col
>0 && ws
.ws_row
>0)
3919 if(!isatty(STDOUT_FILENO
))
3923 columns
= getenv("COLUMNS");
3924 if(columns
&& *columns
)
3928 t
= strtol(columns
, &endptr
, 0);
3929 if(endptr
&& !*endptr
&& (t
>0) && (t
<1000))
3931 width
= static_cast<int>(t
);
3942 bool SystemTools::GetPermissions(const char* file
, mode_t
& mode
)
3950 if ( stat(file
, &st
) < 0 )
3958 bool SystemTools::SetPermissions(const char* file
, mode_t mode
)
3964 if ( !SystemTools::FileExists(file
) )
3968 if ( chmod(file
, mode
) < 0 )
3976 kwsys_stl::string
SystemTools::GetParentDirectory(const char* fileOrDir
)
3978 if ( !fileOrDir
|| !*fileOrDir
)
3982 kwsys_stl::string res
= fileOrDir
;
3983 SystemTools::ConvertToUnixSlashes(res
);
3984 kwsys_stl::string::size_type cc
= res
.size()-1;
3985 if ( res
[cc
] == '/' )
3989 for ( ; cc
> 0; cc
-- )
3991 if ( res
[cc
] == '/' )
3996 return res
.substr(0, cc
);
3999 bool SystemTools::IsSubDirectory(const char* cSubdir
, const char* cDir
)
4001 kwsys_stl::string subdir
= cSubdir
;
4002 kwsys_stl::string dir
= cDir
;
4003 SystemTools::ConvertToUnixSlashes(dir
);
4004 kwsys_stl::string path
= subdir
;
4007 path
= SystemTools::GetParentDirectory(path
.c_str());
4008 if(SystemTools::ComparePath(dir
.c_str(), path
.c_str()))
4013 while ( path
.size() > dir
.size() );
4017 kwsys_stl::string
SystemTools::FileExistsInParentDirectories(const char* fname
,
4018 const char* directory
, const char* toplevel
)
4020 kwsys_stl::string file
= fname
;
4021 SystemTools::ConvertToUnixSlashes(file
);
4022 kwsys_stl::string dir
= directory
;
4023 SystemTools::ConvertToUnixSlashes(dir
);
4024 while ( !dir
.empty() )
4026 kwsys_stl::string path
= dir
+ "/" + file
;
4027 if ( SystemTools::FileExists(path
.c_str()) )
4031 if ( dir
.size() < strlen(toplevel
) )
4035 dir
= SystemTools::GetParentDirectory(dir
.c_str());
4040 void SystemTools::Delay(unsigned int msec
)
4045 // The sleep function gives 1 second resolution and the usleep
4046 // function gives 1e-6 second resolution but on some platforms has a
4047 // maximum sleep time of 1 second. This could be re-implemented to
4048 // use select with masked signals or pselect to mask signals
4049 // atomically. If select is given empty sets and zero as the max
4050 // file descriptor but a non-zero timeout it can be used to block
4051 // for a precise amount of time.
4055 usleep((msec
% 1000) * 1000);
4059 usleep(msec
* 1000);
4064 void SystemTools::ConvertWindowsCommandLineToUnixArguments(
4065 const char *cmd_line
, int *argc
, char ***argv
)
4067 if (!cmd_line
|| !argc
|| !argv
)
4072 // A space delimites an argument except when it is inside a quote
4076 size_t cmd_line_len
= strlen(cmd_line
);
4079 for (i
= 0; i
< cmd_line_len
; i
++)
4081 while (isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4085 if (i
< cmd_line_len
)
4087 if (cmd_line
[i
] == '\"')
4090 while (cmd_line
[i
] != '\"' && i
< cmd_line_len
)
4098 while (!isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4107 (*argv
) = new char* [(*argc
) + 1];
4108 (*argv
)[(*argc
)] = NULL
;
4110 // Set the first arg to be the exec name
4112 (*argv
)[0] = new char [1024];
4114 ::GetModuleFileName(0, (*argv
)[0], 1024);
4116 (*argv
)[0][0] = '\0';
4119 // Allocate the others
4122 for (j
= 1; j
< (*argc
); j
++)
4124 (*argv
)[j
] = new char [cmd_line_len
+ 10];
4132 for (i
= 0; i
< cmd_line_len
; i
++)
4134 while (isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4138 if (i
< cmd_line_len
)
4140 if (cmd_line
[i
] == '\"')
4144 while (cmd_line
[i
] != '\"' && i
< cmd_line_len
)
4148 memcpy((*argv
)[argc_idx
], &cmd_line
[pos
], i
- pos
);
4149 (*argv
)[argc_idx
][i
- pos
] = '\0';
4155 while (!isspace(cmd_line
[i
]) && i
< cmd_line_len
)
4159 memcpy((*argv
)[argc_idx
], &cmd_line
[pos
], i
- pos
);
4160 (*argv
)[argc_idx
][i
- pos
] = '\0';
4167 kwsys_stl::string
SystemTools::GetOperatingSystemNameAndVersion()
4169 kwsys_stl::string res
;
4174 OSVERSIONINFOEX osvi
;
4175 BOOL bOsVersionInfoEx
;
4177 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
4178 // If that fails, try using the OSVERSIONINFO structure.
4180 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
4181 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
4183 bOsVersionInfoEx
= GetVersionEx((OSVERSIONINFO
*)&osvi
);
4184 if (!bOsVersionInfoEx
)
4186 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
4187 if (!GetVersionEx((OSVERSIONINFO
*)&osvi
))
4193 switch (osvi
.dwPlatformId
)
4195 // Test for the Windows NT product family.
4197 case VER_PLATFORM_WIN32_NT
:
4199 // Test for the specific product family.
4201 if (osvi
.dwMajorVersion
== 6 && osvi
.dwMinorVersion
== 0)
4203 #if (_MSC_VER >= 1300)
4204 if (osvi
.wProductType
== VER_NT_WORKSTATION
)
4206 res
+= "Microsoft Windows Vista";
4210 res
+= "Microsoft Windows Server 2008 family";
4213 res
+= "Microsoft Windows Vista or Windows Server 2008";
4217 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
4219 res
+= "Microsoft Windows Server 2003 family";
4222 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
4224 res
+= "Microsoft Windows XP";
4227 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
4229 res
+= "Microsoft Windows 2000";
4232 if (osvi
.dwMajorVersion
<= 4)
4234 res
+= "Microsoft Windows NT";
4237 // Test for specific product on Windows NT 4.0 SP6 and later.
4239 if (bOsVersionInfoEx
)
4241 // Test for the workstation type.
4243 #if (_MSC_VER >= 1300)
4244 if (osvi
.wProductType
== VER_NT_WORKSTATION
)
4246 if (osvi
.dwMajorVersion
== 4)
4248 res
+= " Workstation 4.0";
4250 else if (osvi
.dwMajorVersion
== 5)
4252 if (osvi
.wSuiteMask
& VER_SUITE_PERSONAL
)
4254 res
+= " Home Edition";
4258 res
+= " Professional";
4263 // Test for the server type.
4265 else if (osvi
.wProductType
== VER_NT_SERVER
)
4267 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
4269 if (osvi
.wSuiteMask
& VER_SUITE_DATACENTER
)
4271 res
+= " Datacenter Edition";
4273 else if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
4275 res
+= " Enterprise Edition";
4277 else if (osvi
.wSuiteMask
== VER_SUITE_BLADE
)
4279 res
+= " Web Edition";
4283 res
+= " Standard Edition";
4287 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
4289 if (osvi
.wSuiteMask
& VER_SUITE_DATACENTER
)
4291 res
+= " Datacenter Server";
4293 else if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
4295 res
+= " Advanced Server";
4303 else if (osvi
.dwMajorVersion
<= 4) // Windows NT 4.0
4305 if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
4307 res
+= " Server 4.0, Enterprise Edition";
4311 res
+= " Server 4.0";
4315 #endif // Visual Studio 7 and up
4318 // Test for specific product on Windows NT 4.0 SP5 and earlier
4324 char szProductType
[BUFSIZE
];
4325 DWORD dwBufLen
=BUFSIZE
;
4328 lRet
= RegOpenKeyEx(
4330 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
4331 0, KEY_QUERY_VALUE
, &hKey
);
4332 if (lRet
!= ERROR_SUCCESS
)
4337 lRet
= RegQueryValueEx(hKey
, "ProductType", NULL
, NULL
,
4338 (LPBYTE
) szProductType
, &dwBufLen
);
4340 if ((lRet
!= ERROR_SUCCESS
) || (dwBufLen
> BUFSIZE
))
4347 if (lstrcmpi("WINNT", szProductType
) == 0)
4349 res
+= " Workstation";
4351 if (lstrcmpi("LANMANNT", szProductType
) == 0)
4355 if (lstrcmpi("SERVERNT", szProductType
) == 0)
4357 res
+= " Advanced Server";
4361 sprintf(buffer
, "%ld", osvi
.dwMajorVersion
);
4364 sprintf(buffer
, "%ld", osvi
.dwMinorVersion
);
4368 // Display service pack (if any) and build number.
4370 if (osvi
.dwMajorVersion
== 4 &&
4371 lstrcmpi(osvi
.szCSDVersion
, "Service Pack 6") == 0)
4376 // Test for SP6 versus SP6a.
4378 lRet
= RegOpenKeyEx(
4380 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
4381 0, KEY_QUERY_VALUE
, &hKey
);
4383 if (lRet
== ERROR_SUCCESS
)
4385 res
+= " Service Pack 6a (Build ";
4386 sprintf(buffer
, "%ld", osvi
.dwBuildNumber
& 0xFFFF);
4390 else // Windows NT 4.0 prior to SP6a
4393 res
+= osvi
.szCSDVersion
;
4395 sprintf(buffer
, "%ld", osvi
.dwBuildNumber
& 0xFFFF);
4402 else // Windows NT 3.51 and earlier or Windows 2000 and later
4405 res
+= osvi
.szCSDVersion
;
4407 sprintf(buffer
, "%ld", osvi
.dwBuildNumber
& 0xFFFF);
4414 // Test for the Windows 95 product family.
4416 case VER_PLATFORM_WIN32_WINDOWS
:
4418 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
4420 res
+= "Microsoft Windows 95";
4421 if (osvi
.szCSDVersion
[1] == 'C' || osvi
.szCSDVersion
[1] == 'B')
4427 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
4429 res
+= "Microsoft Windows 98";
4430 if (osvi
.szCSDVersion
[1] == 'A')
4436 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
4438 res
+= "Microsoft Windows Millennium Edition";
4442 case VER_PLATFORM_WIN32s
:
4444 res
+= "Microsoft Win32s";
4452 // ----------------------------------------------------------------------
4453 bool SystemTools::ParseURLProtocol( const kwsys_stl::string
& URL
,
4454 kwsys_stl::string
& protocol
,
4455 kwsys_stl::string
& dataglom
)
4457 // match 0 entire url
4459 // match 2 dataglom following protocol://
4460 kwsys::RegularExpression
urlRe( VTK_URL_PROTOCOL_REGEX
);
4462 if ( ! urlRe
.find( URL
) ) return false;
4464 protocol
= urlRe
.match( 1 );
4465 dataglom
= urlRe
.match( 2 );
4470 // ----------------------------------------------------------------------
4471 bool SystemTools::ParseURL( const kwsys_stl::string
& URL
,
4472 kwsys_stl::string
& protocol
,
4473 kwsys_stl::string
& username
,
4474 kwsys_stl::string
& password
,
4475 kwsys_stl::string
& hostname
,
4476 kwsys_stl::string
& dataport
,
4477 kwsys_stl::string
& database
)
4479 kwsys::RegularExpression
urlRe( VTK_URL_REGEX
);
4480 if ( ! urlRe
.find( URL
) ) return false;
4484 // match 2 mangled user
4486 // match 4 mangled password
4489 // match 7 mangled port
4491 // match 9 database name
4493 protocol
= urlRe
.match( 1 );
4494 username
= urlRe
.match( 3 );
4495 password
= urlRe
.match( 5 );
4496 hostname
= urlRe
.match( 6 );
4497 dataport
= urlRe
.match( 8 );
4498 database
= urlRe
.match( 9 );
4503 // ----------------------------------------------------------------------
4504 // These must NOT be initialized. Default initialization to zero is
4506 unsigned int SystemToolsManagerCount
;
4507 SystemToolsTranslationMap
*SystemTools::TranslationMap
;
4508 SystemToolsTranslationMap
*SystemTools::LongPathMap
;
4510 // SystemToolsManager manages the SystemTools singleton.
4511 // SystemToolsManager should be included in any translation unit
4512 // that will use SystemTools or that implements the singleton
4513 // pattern. It makes sure that the SystemTools singleton is created
4514 // before and destroyed after all other singletons in CMake.
4516 SystemToolsManager::SystemToolsManager()
4518 if(++SystemToolsManagerCount
== 1)
4520 SystemTools::ClassInitialize();
4524 SystemToolsManager::~SystemToolsManager()
4526 if(--SystemToolsManagerCount
== 0)
4528 SystemTools::ClassFinalize();
4532 void SystemTools::ClassInitialize()
4534 // Allocate the translation map first.
4535 SystemTools::TranslationMap
= new SystemToolsTranslationMap
;
4536 SystemTools::LongPathMap
= new SystemToolsTranslationMap
;
4538 // Add some special translation paths for unix. These are not added
4539 // for windows because drive letters need to be maintained. Also,
4540 // there are not sym-links and mount points on windows anyway.
4541 #if !defined(_WIN32) || defined(__CYGWIN__)
4542 // Work-around an SGI problem by always adding this mapping:
4543 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
4544 // The tmp path is frequently a logical path so always keep it:
4545 SystemTools::AddKeepPath("/tmp/");
4547 // If the current working directory is a logical path then keep the
4549 if(const char* pwd
= getenv("PWD"))
4552 if(const char* cwd
= Getcwd(buf
, 2048))
4554 // The current working directory may be a logical path. Find
4555 // the shortest logical path that still produces the correct
4557 kwsys_stl::string cwd_changed
;
4558 kwsys_stl::string pwd_changed
;
4560 // Test progressively shorter logical-to-physical mappings.
4561 kwsys_stl::string pwd_str
= pwd
;
4562 kwsys_stl::string cwd_str
= cwd
;
4563 kwsys_stl::string pwd_path
;
4564 Realpath(pwd
, pwd_path
);
4565 while(cwd_str
== pwd_path
&& cwd_str
!= pwd_str
)
4567 // The current pair of paths is a working logical mapping.
4568 cwd_changed
= cwd_str
;
4569 pwd_changed
= pwd_str
;
4571 // Strip off one directory level and see if the logical
4572 // mapping still works.
4573 pwd_str
= SystemTools::GetFilenamePath(pwd_str
.c_str());
4574 cwd_str
= SystemTools::GetFilenamePath(cwd_str
.c_str());
4575 Realpath(pwd_str
.c_str(), pwd_path
);
4578 // Add the translation to keep the logical path name.
4579 if(!cwd_changed
.empty() && !pwd_changed
.empty())
4581 SystemTools::AddTranslationPath(cwd_changed
.c_str(),
4582 pwd_changed
.c_str());
4589 void SystemTools::ClassFinalize()
4591 delete SystemTools::TranslationMap
;
4592 delete SystemTools::LongPathMap
;
4596 } // namespace KWSYS_NAMESPACE
4598 #if defined(_MSC_VER) && defined(_DEBUG)
4599 # include <crtdbg.h>
4601 # include <stdlib.h>
4602 namespace KWSYS_NAMESPACE
4605 static int SystemToolsDebugReport(int, char* message
, int*)
4607 fprintf(stderr
, "%s", message
);
4609 return 1; // no further reporting required
4612 void SystemTools::EnableMSVCDebugHook()
4614 if (getenv("DART_TEST_FROM_DART"))
4616 _CrtSetReportHook(SystemToolsDebugReport
);
4620 } // namespace KWSYS_NAMESPACE
4622 namespace KWSYS_NAMESPACE
4624 void SystemTools::EnableMSVCDebugHook() {}
4625 } // namespace KWSYS_NAMESPACE