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(SystemTools.hxx)
16 #include KWSYS_HEADER(Directory.hxx)
18 #include KWSYS_HEADER(ios/iostream)
19 #include KWSYS_HEADER(ios/fstream)
20 #include KWSYS_HEADER(ios/sstream)
23 # pragma warning (disable: 4786)
29 # include <malloc.h> /* for malloc/free on QNX */
37 // support for realpath call
40 #include <sys/param.h>
42 #include <sys/ioctl.h>
47 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__))
51 #define _unlink unlink
52 inline int Mkdir(const char* dir
)
56 inline int Rmdir(const char* dir
)
60 inline const char* Getcwd(char* buf
, unsigned int len
)
62 return _getcwd(buf
, len
);
64 inline int Chdir(const char* dir
)
66 #if defined(__BORLANDC__)
72 inline void Realpath(const char *path
, kwsys_stl::string
& resolved_path
)
75 char fullpath
[MAX_PATH
];
76 if( GetFullPathName(path
, sizeof(fullpath
), fullpath
, &ptemp
) )
78 resolved_path
= fullpath
;
79 KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path
);
83 #include <sys/types.h>
86 inline int Mkdir(const char* dir
)
88 return mkdir(dir
, 00777);
90 inline int Rmdir(const char* dir
)
94 inline const char* Getcwd(char* buf
, unsigned int len
)
96 return getcwd(buf
, len
);
98 inline int Chdir(const char* dir
)
102 inline void Realpath(const char *path
, kwsys_stl::string
& resolved_path
)
105 char resolved_name
[MAXPATHLEN
];
108 char resolved_name
[PATH_MAX
];
110 char resolved_name
[5024];
114 realpath(path
, resolved_name
);
115 resolved_path
= resolved_name
;
119 #if !defined(_WIN32) && defined(__COMO__)
120 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
123 extern FILE *popen (__const
char *__command
, __const
char *__modes
) __THROW
;
124 extern int pclose (FILE *__stream
) __THROW
;
125 extern char *realpath (__const
char *__restrict __name
,
126 char *__restrict __resolved
) __THROW
;
127 extern char *strdup (__const
char *__s
) __THROW
;
128 extern int putenv (char *__string
) __THROW
;
132 /* Implement floattime() for various platforms */
133 // Taken from Python 2.1.3
135 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
136 # include <sys/timeb.h>
138 # if defined( __BORLANDC__)
141 # else // Visual studio?
142 # define FTIME _ftime
143 # define TIMEB _timeb
145 #elif defined( __CYGWIN__ ) || defined( __linux__ )
146 # include <sys/time.h>
148 # define HAVE_GETTIMEOFDAY
151 namespace KWSYS_NAMESPACE
154 class SystemToolsTranslationMap
:
155 public kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>
160 SystemTools::GetTime(void)
162 /* There are three ways to get the time:
163 (1) gettimeofday() -- resolution in microseconds
164 (2) ftime() -- resolution in milliseconds
165 (3) time() -- resolution in seconds
166 In all cases the return value is a float in seconds.
167 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
168 fail, so we fall back on ftime() or time().
169 Note: clock resolution does not imply clock accuracy! */
170 #ifdef HAVE_GETTIMEOFDAY
173 #ifdef GETTIMEOFDAY_NO_TZ
174 if (gettimeofday(&t
) == 0)
175 return (double)t
.tv_sec
+ t
.tv_usec
*0.000001;
176 #else /* !GETTIMEOFDAY_NO_TZ */
177 if (gettimeofday(&t
, (struct timezone
*)NULL
) == 0)
178 return (double)t
.tv_sec
+ t
.tv_usec
*0.000001;
179 #endif /* !GETTIMEOFDAY_NO_TZ */
181 #endif /* !HAVE_GETTIMEOFDAY */
183 #if defined(HAVE_FTIME)
186 return (double)t
.time
+ (double)t
.millitm
* (double)0.001;
187 #else /* !HAVE_FTIME */
191 #endif /* !HAVE_FTIME */
195 // adds the elements of the env variable path to the arg passed in
196 void SystemTools::GetPath(kwsys_stl::vector
<kwsys_stl::string
>& path
, const char* env
)
198 #if defined(_WIN32) && !defined(__CYGWIN__)
199 const char* pathSep
= ";";
201 const char* pathSep
= ":";
207 const char* cpathEnv
= SystemTools::GetEnv(env
);
213 kwsys_stl::string pathEnv
= cpathEnv
;
215 // A hack to make the below algorithm work.
216 if(pathEnv
[pathEnv
.length()-1] != ':')
220 kwsys_stl::string::size_type start
=0;
224 kwsys_stl::string::size_type endpos
= pathEnv
.find(pathSep
, start
);
225 if(endpos
!= kwsys_stl::string::npos
)
227 path
.push_back(pathEnv
.substr(start
, endpos
-start
));
235 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
236 i
!= path
.end(); ++i
)
238 SystemTools::ConvertToUnixSlashes(*i
);
242 const char* SystemTools::GetEnv(const char* key
)
247 bool SystemTools::GetEnv(const char* key
, kwsys_stl::string
& result
)
249 const char* v
= getenv(key
);
261 const char* SystemTools::GetExecutableExtension()
263 #if defined(_WIN32) || defined(__CYGWIN__)
271 bool SystemTools::MakeDirectory(const char* path
)
273 if(SystemTools::FileExists(path
))
277 kwsys_stl::string dir
= path
;
282 SystemTools::ConvertToUnixSlashes(dir
);
284 kwsys_stl::string::size_type pos
= dir
.find(':');
285 if(pos
== kwsys_stl::string::npos
)
289 kwsys_stl::string topdir
;
290 while((pos
= dir
.find('/', pos
)) != kwsys_stl::string::npos
)
292 topdir
= dir
.substr(0, pos
);
293 Mkdir(topdir
.c_str());
296 if(dir
[dir
.size()-1] == '/')
298 topdir
= dir
.substr(0, dir
.size());
304 if(Mkdir(topdir
.c_str()) != 0)
306 // There is a bug in the Borland Run time library which makes MKDIR
307 // return EACCES when it should return EEXISTS
308 // if it is some other error besides directory exists
310 if( (errno
!= EEXIST
)
323 // replace replace with with as many times as it shows up in source.
324 // write the result into source.
325 void SystemTools::ReplaceString(kwsys_stl::string
& source
,
329 const char *src
= source
.c_str();
330 char *searchPos
= const_cast<char *>(strstr(src
,replace
));
332 // get out quick if string is not found
338 // perform replacements until done
339 size_t replaceSize
= strlen(replace
);
340 char *orig
= strdup(src
);
341 char *currentPos
= orig
;
342 searchPos
= searchPos
- src
+ orig
;
344 // initialize the result
345 source
.erase(source
.begin(),source
.end());
349 source
+= currentPos
;
350 currentPos
= searchPos
+ replaceSize
;
353 searchPos
= strstr(currentPos
,replace
);
357 // copy any trailing text
358 source
+= currentPos
;
362 // Read a registry value.
364 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
365 // => will return the data of the "default" value of the key
366 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
367 // => will return the data of the "Root" value of the key
369 #if defined(_WIN32) && !defined(__CYGWIN__)
370 bool SystemTools::ReadRegistryValue(const char *key
, kwsys_stl::string
&value
)
373 kwsys_stl::string primary
= key
;
374 kwsys_stl::string second
;
375 kwsys_stl::string valuename
;
377 size_t start
= primary
.find("\\");
378 if (start
== kwsys_stl::string::npos
)
383 size_t valuenamepos
= primary
.find(";");
384 if (valuenamepos
!= kwsys_stl::string::npos
)
386 valuename
= primary
.substr(valuenamepos
+1);
389 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
390 primary
= primary
.substr(0, start
);
392 HKEY primaryKey
= HKEY_CURRENT_USER
;
393 if (primary
== "HKEY_CURRENT_USER")
395 primaryKey
= HKEY_CURRENT_USER
;
397 if (primary
== "HKEY_CURRENT_CONFIG")
399 primaryKey
= HKEY_CURRENT_CONFIG
;
401 if (primary
== "HKEY_CLASSES_ROOT")
403 primaryKey
= HKEY_CLASSES_ROOT
;
405 if (primary
== "HKEY_LOCAL_MACHINE")
407 primaryKey
= HKEY_LOCAL_MACHINE
;
409 if (primary
== "HKEY_USERS")
411 primaryKey
= HKEY_USERS
;
415 if(RegOpenKeyEx(primaryKey
,
419 &hKey
) != ERROR_SUCCESS
)
425 DWORD dwType
, dwSize
;
428 if(RegQueryValueEx(hKey
,
429 (LPTSTR
)valuename
.c_str(),
433 &dwSize
) == ERROR_SUCCESS
)
435 if (dwType
== REG_SZ
)
446 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string
&)
453 // Write a registry value.
455 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
456 // => will set the data of the "default" value of the key
457 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
458 // => will set the data of the "Root" value of the key
460 #if defined(_WIN32) && !defined(__CYGWIN__)
461 bool SystemTools::WriteRegistryValue(const char *key
, const char *value
)
463 kwsys_stl::string primary
= key
;
464 kwsys_stl::string second
;
465 kwsys_stl::string valuename
;
467 size_t start
= primary
.find("\\");
468 if (start
== kwsys_stl::string::npos
)
473 size_t valuenamepos
= primary
.find(";");
474 if (valuenamepos
!= kwsys_stl::string::npos
)
476 valuename
= primary
.substr(valuenamepos
+1);
479 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
480 primary
= primary
.substr(0, start
);
482 HKEY primaryKey
= HKEY_CURRENT_USER
;
483 if (primary
== "HKEY_CURRENT_USER")
485 primaryKey
= HKEY_CURRENT_USER
;
487 if (primary
== "HKEY_CURRENT_CONFIG")
489 primaryKey
= HKEY_CURRENT_CONFIG
;
491 if (primary
== "HKEY_CLASSES_ROOT")
493 primaryKey
= HKEY_CLASSES_ROOT
;
495 if (primary
== "HKEY_LOCAL_MACHINE")
497 primaryKey
= HKEY_LOCAL_MACHINE
;
499 if (primary
== "HKEY_USERS")
501 primaryKey
= HKEY_USERS
;
506 if(RegCreateKeyEx(primaryKey
,
510 REG_OPTION_NON_VOLATILE
,
514 &dwDummy
) != ERROR_SUCCESS
)
519 if(RegSetValueEx(hKey
,
520 (LPTSTR
)valuename
.c_str(),
524 (DWORD
)(strlen(value
) + 1)) == ERROR_SUCCESS
)
531 bool SystemTools::WriteRegistryValue(const char *, const char *)
537 // Delete a registry value.
539 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
540 // => will delete the data of the "default" value of the key
541 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
542 // => will delete the data of the "Root" value of the key
544 #if defined(_WIN32) && !defined(__CYGWIN__)
545 bool SystemTools::DeleteRegistryValue(const char *key
)
547 kwsys_stl::string primary
= key
;
548 kwsys_stl::string second
;
549 kwsys_stl::string valuename
;
551 size_t start
= primary
.find("\\");
552 if (start
== kwsys_stl::string::npos
)
557 size_t valuenamepos
= primary
.find(";");
558 if (valuenamepos
!= kwsys_stl::string::npos
)
560 valuename
= primary
.substr(valuenamepos
+1);
563 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
564 primary
= primary
.substr(0, start
);
566 HKEY primaryKey
= HKEY_CURRENT_USER
;
567 if (primary
== "HKEY_CURRENT_USER")
569 primaryKey
= HKEY_CURRENT_USER
;
571 if (primary
== "HKEY_CURRENT_CONFIG")
573 primaryKey
= HKEY_CURRENT_CONFIG
;
575 if (primary
== "HKEY_CLASSES_ROOT")
577 primaryKey
= HKEY_CLASSES_ROOT
;
579 if (primary
== "HKEY_LOCAL_MACHINE")
581 primaryKey
= HKEY_LOCAL_MACHINE
;
583 if (primary
== "HKEY_USERS")
585 primaryKey
= HKEY_USERS
;
589 if(RegOpenKeyEx(primaryKey
,
593 &hKey
) != ERROR_SUCCESS
)
599 if(RegDeleteValue(hKey
,
600 (LPTSTR
)valuename
.c_str()) == ERROR_SUCCESS
)
609 bool SystemTools::DeleteRegistryValue(const char *)
615 bool SystemTools::SameFile(const char* file1
, const char* file2
)
618 HANDLE hFile1
, hFile2
;
620 hFile1
= CreateFile( file1
,
625 FILE_FLAG_BACKUP_SEMANTICS
,
628 hFile2
= CreateFile( file2
,
633 FILE_FLAG_BACKUP_SEMANTICS
,
636 if( hFile1
== INVALID_HANDLE_VALUE
|| hFile2
== INVALID_HANDLE_VALUE
)
638 if(hFile1
!= INVALID_HANDLE_VALUE
)
642 if(hFile2
!= INVALID_HANDLE_VALUE
)
649 BY_HANDLE_FILE_INFORMATION fiBuf1
;
650 BY_HANDLE_FILE_INFORMATION fiBuf2
;
651 GetFileInformationByHandle( hFile1
, &fiBuf1
);
652 GetFileInformationByHandle( hFile2
, &fiBuf2
);
655 return (fiBuf1
.dwVolumeSerialNumber
== fiBuf2
.dwVolumeSerialNumber
&&
656 fiBuf1
.nFileIndexHigh
== fiBuf2
.nFileIndexHigh
&&
657 fiBuf1
.nFileIndexLow
== fiBuf2
.nFileIndexLow
);
659 struct stat fileStat1
, fileStat2
;
660 if (stat(file1
, &fileStat1
) == 0 && stat(file2
, &fileStat2
) == 0)
662 // see if the files are the same file
663 // check the device inode and size
664 if(memcmp(&fileStat2
.st_dev
, &fileStat1
.st_dev
, sizeof(fileStat1
.st_dev
)) == 0 &&
665 memcmp(&fileStat2
.st_ino
, &fileStat1
.st_ino
, sizeof(fileStat1
.st_ino
)) == 0 &&
666 fileStat2
.st_size
== fileStat1
.st_size
677 // return true if the file exists
678 bool SystemTools::FileExists(const char* filename
)
681 # define access _access
686 if ( access(filename
, R_OK
) != 0 )
697 bool SystemTools::FileTimeCompare(const char* f1
, const char* f2
,
700 // Default to same time.
702 #if !defined(_WIN32) || defined(__CYGWIN__)
703 // POSIX version. Use stat function to get file modification time.
705 if(stat(f1
, &s1
) != 0)
710 if(stat(f2
, &s2
) != 0)
714 # if KWSYS_STAT_HAS_ST_MTIM
715 // Compare using nanosecond resolution.
716 if(s1
.st_mtim
.tv_sec
< s2
.st_mtim
.tv_sec
)
720 else if(s1
.st_mtim
.tv_sec
> s2
.st_mtim
.tv_sec
)
724 else if(s1
.st_mtim
.tv_nsec
< s2
.st_mtim
.tv_nsec
)
728 else if(s1
.st_mtim
.tv_nsec
> s2
.st_mtim
.tv_nsec
)
733 // Compare using 1 second resolution.
734 if(s1
.st_mtime
< s2
.st_mtime
)
738 else if(s1
.st_mtime
> s2
.st_mtime
)
744 // Windows version. Create file handles and get the modification times.
745 HANDLE hf1
= CreateFile(f1
, GENERIC_READ
, FILE_SHARE_READ
,
746 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
748 if(hf1
== INVALID_HANDLE_VALUE
)
753 if(!GetFileTime(hf1
, 0, 0, &tf1
))
759 HANDLE hf2
= CreateFile(f2
, GENERIC_READ
, FILE_SHARE_READ
,
760 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
762 if(hf2
== INVALID_HANDLE_VALUE
)
767 if(!GetFileTime(hf2
, 0, 0, &tf2
))
774 // Compare the file times using resolution provided by system call.
775 *result
= (int)CompareFileTime(&tf1
, &tf2
);
781 // Return a capitalized string (i.e the first letter is uppercased, all other
783 kwsys_stl::string
SystemTools::Capitalized(const kwsys_stl::string
& s
)
791 n
[0] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[0]));
792 for (size_t i
= 1; i
< s
.size(); i
++)
794 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
799 // Return capitalized words
800 kwsys_stl::string
SystemTools::CapitalizedWords(const kwsys_stl::string
& s
)
802 kwsys_stl::string
n(s
);
803 for (size_t i
= 0; i
< s
.size(); i
++)
805 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
807 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
813 // Return uncapitalized words
814 kwsys_stl::string
SystemTools::UnCapitalizedWords(const kwsys_stl::string
& s
)
816 kwsys_stl::string
n(s
);
817 for (size_t i
= 0; i
< s
.size(); i
++)
819 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
821 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
827 kwsys_stl::string
SystemTools::AddSpaceBetweenCapitalizedWords(
828 const kwsys_stl::string
& s
)
835 for (size_t i
= 1; i
< s
.size(); i
++)
837 if (isupper(s
[i
]) && !isspace(s
[i
- 1]) && !isupper(s
[i
- 1]))
847 char* SystemTools::AppendStrings(const char* str1
, const char* str2
)
851 return SystemTools::DuplicateString(str2
);
855 return SystemTools::DuplicateString(str1
);
857 size_t len1
= strlen(str1
);
858 char *newstr
= new char[len1
+ strlen(str2
) + 1];
863 strcpy(newstr
, str1
);
864 strcat(newstr
+ len1
, str2
);
868 char* SystemTools::AppendStrings(
869 const char* str1
, const char* str2
, const char* str3
)
873 return SystemTools::AppendStrings(str2
, str3
);
877 return SystemTools::AppendStrings(str1
, str3
);
881 return SystemTools::AppendStrings(str1
, str2
);
884 size_t len1
= strlen(str1
), len2
= strlen(str2
);
885 char *newstr
= new char[len1
+ len2
+ strlen(str3
) + 1];
890 strcpy(newstr
, str1
);
891 strcat(newstr
+ len1
, str2
);
892 strcat(newstr
+ len1
+ len2
, str3
);
896 // Return a lower case string
897 kwsys_stl::string
SystemTools::LowerCase(const kwsys_stl::string
& s
)
901 for (size_t i
= 0; i
< s
.size(); i
++)
903 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
908 // Return a lower case string
909 kwsys_stl::string
SystemTools::UpperCase(const kwsys_stl::string
& s
)
913 for (size_t i
= 0; i
< s
.size(); i
++)
915 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
920 // Count char in string
921 size_t SystemTools::CountChar(const char* str
, char c
)
939 // Remove chars in string
940 char* SystemTools::RemoveChars(const char* str
, const char *toremove
)
946 char *clean_str
= new char [strlen(str
) + 1];
947 char *ptr
= clean_str
;
950 const char *str2
= toremove
;
951 while (*str2
&& *str
!= *str2
)
965 // Remove chars in string
966 char* SystemTools::RemoveCharsButUpperHex(const char* str
)
972 char *clean_str
= new char [strlen(str
) + 1];
973 char *ptr
= clean_str
;
976 if ((*str
>= '0' && *str
<= '9') || (*str
>= 'A' && *str
<= 'H'))
986 // Replace chars in string
987 char* SystemTools::ReplaceChars(char* str
, const char *toreplace
, char replacement
)
994 const char *ptr2
= toreplace
;
1009 // Returns if string starts with another string
1010 bool SystemTools::StringStartsWith(const char* str1
, const char* str2
)
1016 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1017 return len1
>= len2
&& !strncmp(str1
, str2
, len2
) ? true : false;
1020 // Returns if string ends with another string
1021 bool SystemTools::StringEndsWith(const char* str1
, const char* str2
)
1027 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1028 return len1
>= len2
&& !strncmp(str1
+ (len1
- len2
), str2
, len2
) ? true : false;
1031 // Returns a pointer to the last occurence of str2 in str1
1032 const char* SystemTools::FindLastString(const char* str1
, const char* str2
)
1039 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1042 const char *ptr
= str1
+ len1
- len2
;
1045 if (!strncmp(ptr
, str2
, len2
))
1049 } while (ptr
-- != str1
);
1056 char* SystemTools::DuplicateString(const char* str
)
1060 char *newstr
= new char [strlen(str
) + 1];
1061 return strcpy(newstr
, str
);
1066 // Return a cropped string
1067 kwsys_stl::string
SystemTools::CropString(const kwsys_stl::string
& s
,
1070 if (!s
.size() || max_len
== 0 || max_len
>= s
.size())
1075 kwsys_stl::string n
;
1078 size_t middle
= max_len
/ 2;
1080 n
+= s
.substr(0, middle
);
1081 n
+= s
.substr(s
.size() - (max_len
- middle
), kwsys_stl::string::npos
);
1088 n
[middle
- 1] = '.';
1091 n
[middle
+ 1] = '.';
1099 //----------------------------------------------------------------------------
1100 int SystemTools::EstimateFormatLength(const char *format
, va_list ap
)
1107 // Quick-hack attempt at estimating the length of the string.
1108 // Should never under-estimate.
1110 // Start with the length of the format string itself.
1112 int length
= strlen(format
);
1114 // Increase the length for every argument in the format.
1116 const char* cur
= format
;
1121 // Skip "%%" since it doesn't correspond to a va_arg.
1124 while(!int(isalpha(*cur
)))
1132 // Check the length of the string.
1133 char* s
= va_arg(ap
, char*);
1136 length
+= strlen(s
);
1143 // Assume the argument contributes no more than 64 characters.
1146 // Eat the argument.
1147 static_cast<void>(va_arg(ap
, double));
1151 // Assume the argument contributes no more than 64 characters.
1154 // Eat the argument.
1155 static_cast<void>(va_arg(ap
, int));
1160 // Move past the characters just tested.
1168 // convert windows slashes to unix slashes
1169 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string
& path
)
1171 kwsys_stl::string::size_type pos
= 0;
1172 while((pos
= path
.find('\\', pos
)) != kwsys_stl::string::npos
)
1174 // make sure we don't convert an escaped space to a unix slash
1175 if(pos
< path
.size()-1)
1177 if(path
[pos
+1] != ' ')
1184 // Remove all // from the path just like most unix shells
1188 // However, on windows if the first characters are both slashes,
1189 // then keep them that way, so that network paths can be handled.
1195 while((pos
= path
.find("//", start_find
)) != kwsys_stl::string::npos
)
1197 SystemTools::ReplaceString(path
, "//", "/");
1200 // remove any trailing slash
1201 if(path
.size() > 1 && path
[path
.size()-1] == '/')
1203 path
= path
.substr(0, path
.size()-1);
1206 // if there is a tilda ~ then replace it with HOME
1207 if(path
.find("~") == 0)
1211 path
= kwsys_stl::string(getenv("HOME")) + path
.substr(1);
1216 // change // to /, and escape any spaces in the path
1217 kwsys_stl::string
SystemTools::ConvertToUnixOutputPath(const char* path
)
1219 kwsys_stl::string ret
= path
;
1221 // remove // except at the beginning might be a cygwin drive
1222 kwsys_stl::string::size_type pos
= 1;
1223 while((pos
= ret
.find("//", pos
)) != kwsys_stl::string::npos
)
1227 // now escape spaces if there is a space in the path
1228 if(ret
.find(" ") != kwsys_stl::string::npos
)
1230 kwsys_stl::string result
= "";
1232 for(const char* ch
= ret
.c_str(); *ch
!= '\0'; ++ch
)
1234 // if it is already escaped then don't try to escape it again
1235 if(*ch
== ' ' && lastch
!= '\\')
1247 kwsys_stl::string
SystemTools::ConvertToOutputPath(const char* path
)
1249 #if defined(_WIN32) && !defined(__CYGWIN__)
1250 return SystemTools::ConvertToWindowsOutputPath(path
);
1252 return SystemTools::ConvertToUnixOutputPath(path
);
1256 // remove double slashes not at the start
1257 kwsys_stl::string
SystemTools::ConvertToWindowsOutputPath(const char* path
)
1259 kwsys_stl::string ret
= path
;
1260 kwsys_stl::string::size_type pos
= 0;
1261 // first convert all of the slashes
1262 while((pos
= ret
.find('/', pos
)) != kwsys_stl::string::npos
)
1267 // check for really small paths
1272 // now clean up a bit and remove double slashes
1273 // Only if it is not the first position in the path which is a network
1275 pos
= 1; // start at position 1
1278 pos
= 2; // if the string is already quoted then start at 2
1284 while((pos
= ret
.find("\\\\", pos
)) != kwsys_stl::string::npos
)
1288 // now double quote the path if it has spaces in it
1289 // and is not already double quoted
1290 if(ret
.find(" ") != kwsys_stl::string::npos
1293 kwsys_stl::string result
;
1294 result
= "\"" + ret
+ "\"";
1300 bool SystemTools::CopyFileIfDifferent(const char* source
,
1301 const char* destination
)
1303 if(SystemTools::FilesDiffer(source
, destination
))
1305 return SystemTools::CopyFileAlways(source
, destination
);
1311 bool SystemTools::FilesDiffer(const char* source
,
1312 const char* destination
)
1314 struct stat statSource
;
1315 if (stat(source
, &statSource
) != 0)
1320 struct stat statDestination
;
1321 if (stat(destination
, &statDestination
) != 0)
1326 if(statSource
.st_size
!= statDestination
.st_size
)
1331 if(statSource
.st_size
== 0)
1336 #if defined(_WIN32) || defined(__CYGWIN__)
1337 kwsys_ios::ifstream
finSource(source
, (kwsys_ios::ios::binary
|
1338 kwsys_ios::ios::in
));
1339 kwsys_ios::ifstream
finDestination(destination
, (kwsys_ios::ios::binary
|
1340 kwsys_ios::ios::in
));
1342 kwsys_ios::ifstream
finSource(source
);
1343 kwsys_ios::ifstream
finDestination(destination
);
1345 if(!finSource
|| !finDestination
)
1350 char* source_buf
= new char[statSource
.st_size
];
1351 char* dest_buf
= new char[statSource
.st_size
];
1353 finSource
.read(source_buf
, statSource
.st_size
);
1354 finDestination
.read(dest_buf
, statSource
.st_size
);
1356 if(statSource
.st_size
!= static_cast<long>(finSource
.gcount()) ||
1357 statSource
.st_size
!= static_cast<long>(finDestination
.gcount()))
1359 // Failed to read files.
1360 delete [] source_buf
;
1364 int ret
= memcmp((const void*)source_buf
,
1365 (const void*)dest_buf
,
1366 statSource
.st_size
);
1369 delete [] source_buf
;
1376 * Copy a file named by "source" to the file named by "destination".
1378 bool SystemTools::CopyFileAlways(const char* source
, const char* destination
)
1380 // If files are the same do not copy
1381 if ( SystemTools::SameFile(source
, destination
) )
1387 bool perms
= SystemTools::GetPermissions(source
, perm
);
1389 const int bufferSize
= 4096;
1390 char buffer
[bufferSize
];
1392 // If destination is a directory, try to create a file with the same
1393 // name as the source in that directory.
1395 kwsys_stl::string new_destination
;
1396 if(SystemTools::FileExists(destination
) &&
1397 SystemTools::FileIsDirectory(destination
))
1399 new_destination
= destination
;
1400 SystemTools::ConvertToUnixSlashes(new_destination
);
1401 new_destination
+= '/';
1402 kwsys_stl::string source_name
= source
;
1403 new_destination
+= SystemTools::GetFilenameName(source_name
);
1404 destination
= new_destination
.c_str();
1407 // Create destination directory
1409 kwsys_stl::string destination_dir
= destination
;
1410 destination_dir
= SystemTools::GetFilenamePath(destination_dir
);
1411 SystemTools::MakeDirectory(destination_dir
.c_str());
1415 #if defined(_WIN32) || defined(__CYGWIN__)
1416 kwsys_ios::ifstream
fin(source
,
1417 kwsys_ios::ios::binary
| kwsys_ios::ios::in
);
1419 kwsys_ios::ifstream
fin(source
);
1426 // try and remove the destination file so that read only destination files
1427 // can be written to.
1428 // If the remove fails continue so that files in read only directories
1429 // that do not allow file removal can be modified.
1430 SystemTools::RemoveFile(destination
);
1432 #if defined(_WIN32) || defined(__CYGWIN__)
1433 kwsys_ios::ofstream
fout(destination
,
1434 kwsys_ios::ios::binary
| kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1436 kwsys_ios::ofstream
fout(destination
,
1437 kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1444 // This copy loop is very sensitive on certain platforms with
1445 // slightly broken stream libraries (like HPUX). Normally, it is
1446 // incorrect to not check the error condition on the fin.read()
1447 // before using the data, but the fin.gcount() will be zero if an
1448 // error occurred. Therefore, the loop should be safe everywhere.
1451 fin
.read(buffer
, bufferSize
);
1454 fout
.write(buffer
, fin
.gcount());
1458 // Make sure the operating system has finished writing the file
1459 // before closing it. This will ensure the file is finished before
1467 struct stat statSource
, statDestination
;
1468 statSource
.st_size
= 12345;
1469 statDestination
.st_size
= 12345;
1470 if(stat(source
, &statSource
) != 0)
1474 else if(stat(destination
, &statDestination
) != 0)
1478 else if(statSource
.st_size
!= statDestination
.st_size
)
1484 if ( !SystemTools::SetPermissions(destination
, perm
) )
1493 * Copy a directory content from "source" directory to the directory named by
1496 bool SystemTools::CopyADirectory(const char* source
, const char* destination
)
1501 if ( !SystemTools::MakeDirectory(destination
) )
1505 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
1507 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
1508 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
1510 kwsys_stl::string fullPath
= source
;
1512 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1513 if(SystemTools::FileIsDirectory(fullPath
.c_str()))
1515 kwsys_stl::string fullDestPath
= destination
;
1516 fullDestPath
+= "/";
1517 fullDestPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1518 if (!SystemTools::CopyADirectory(fullPath
.c_str(), fullDestPath
.c_str()))
1525 if(!SystemTools::CopyFileAlways(fullPath
.c_str(), destination
))
1537 // return size of file; also returns zero if no file exists
1538 unsigned long SystemTools::FileLength(const char* filename
)
1541 if (stat(filename
, &fs
) != 0)
1547 return static_cast<unsigned long>(fs
.st_size
);
1551 int SystemTools::Strucmp(const char *s1
, const char *s2
)
1553 // lifted from Graphvis http://www.graphviz.org
1554 while ((*s1
!= '\0')
1555 && (tolower(*s1
) == tolower(*s2
)))
1561 return tolower(*s1
) - tolower(*s2
);
1565 // return file's modified time
1566 long int SystemTools::ModifiedTime(const char* filename
)
1569 if (stat(filename
, &fs
) != 0)
1575 return (long int)fs
.st_mtime
;
1579 // return file's creation time
1580 long int SystemTools::CreationTime(const char* filename
)
1583 if (stat(filename
, &fs
) != 0)
1589 return fs
.st_ctime
>= 0 ? (long int)fs
.st_ctime
: 0;
1593 bool SystemTools::ConvertDateMacroString(const char *str
, time_t *tmt
)
1595 if (!str
|| !tmt
|| strlen(str
) < 12)
1603 // The compilation date of the current source file. The date is a string
1604 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
1605 // dates generated by the library function asctime declared in TIME.H.
1607 // index: 012345678901
1608 // format: Mmm dd yyyy
1609 // example: Dec 19 2003
1611 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1614 strcpy(buffer
, str
);
1617 char *ptr
= strstr(month_names
, buffer
);
1623 int month
= (ptr
- month_names
) / 3;
1624 int day
= atoi(buffer
+ 4);
1625 int year
= atoi(buffer
+ 7);
1634 tmt2
.tm_mon
= month
;
1635 tmt2
.tm_year
= year
- 1900;
1637 *tmt
= mktime(&tmt2
);
1641 bool SystemTools::ConvertTimeStampMacroString(const char *str
, time_t *tmt
)
1643 if (!str
|| !tmt
|| strlen(str
) < 27)
1651 // The date and time of the last modification of the current source file,
1652 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
1653 /// where Ddd is the abbreviated day of the week and Date is an integer
1656 // index: 0123456789
1659 // format: Ddd Mmm Date hh:mm:ss yyyy
1660 // example: Fri Dec 19 14:34:58 2003
1662 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1665 strcpy(buffer
, str
);
1668 char *ptr
= strstr(month_names
, buffer
+ 4);
1674 int month
= (ptr
- month_names
) / 3;
1675 int day
= atoi(buffer
+ 8);
1676 int hour
= atoi(buffer
+ 11);
1677 int min
= atoi(buffer
+ 14);
1678 int sec
= atoi(buffer
+ 17);
1679 int year
= atoi(buffer
+ 20);
1682 tmt2
.tm_hour
= hour
;
1688 tmt2
.tm_mon
= month
;
1689 tmt2
.tm_year
= year
- 1900;
1691 *tmt
= mktime(&tmt2
);
1695 kwsys_stl::string
SystemTools::GetLastSystemError()
1701 bool SystemTools::RemoveFile(const char* source
)
1705 if ( !SystemTools::GetPermissions(source
, mode
) )
1709 /* Win32 unlink is stupid --- it fails if the file is read-only */
1710 SystemTools::SetPermissions(source
, S_IWRITE
);
1712 bool res
= unlink(source
) != 0 ? false : true;
1716 SystemTools::SetPermissions(source
, mode
);
1722 bool SystemTools::RemoveADirectory(const char* source
)
1727 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
1729 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
1730 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
1732 kwsys_stl::string fullPath
= source
;
1734 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1735 if(SystemTools::FileIsDirectory(fullPath
.c_str()))
1737 if (!SystemTools::RemoveADirectory(fullPath
.c_str()))
1744 if(!SystemTools::RemoveFile(fullPath
.c_str()))
1752 return (Rmdir(source
) == 0);
1756 * Find the file the given name. Searches the given path and then
1757 * the system search path. Returns the full path to the file if it is
1758 * found. Otherwise, the empty string is returned.
1760 kwsys_stl::string SystemTools
1761 ::FindFile(const char* name
,
1762 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
)
1764 // Add the system search path to our path first
1765 kwsys_stl::vector
<kwsys_stl::string
> path
;
1766 SystemTools::GetPath(path
, "CMAKE_FILE_PATH");
1767 SystemTools::GetPath(path
);
1768 // now add the additional paths
1769 path
.insert(path
.end(), userPaths
.begin(), userPaths
.end());
1770 // now look for the file
1771 kwsys_stl::string tryPath
;
1772 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
1773 p
!= path
.end(); ++p
)
1778 if(SystemTools::FileExists(tryPath
.c_str()) &&
1779 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1781 return SystemTools::CollapseFullPath(tryPath
.c_str());
1784 // Couldn't find the file.
1789 * Find the executable with the given name. Searches the given path and then
1790 * the system search path. Returns the full path to the executable if it is
1791 * found. Otherwise, the empty string is returned.
1793 kwsys_stl::string
SystemTools::FindProgram(
1795 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
1796 bool no_system_path
)
1802 // See if the executable exists as written.
1803 if(SystemTools::FileExists(name
) &&
1804 !SystemTools::FileIsDirectory(name
))
1806 return SystemTools::CollapseFullPath(name
);
1808 kwsys_stl::string tryPath
= name
;
1809 tryPath
+= SystemTools::GetExecutableExtension();
1810 if(SystemTools::FileExists(tryPath
.c_str()) &&
1811 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1813 return SystemTools::CollapseFullPath(tryPath
.c_str());
1815 kwsys_stl::vector
<kwsys_stl::string
> path
;
1816 SystemTools::GetPath(path
, "CMAKE_PROGRAM_PATH");
1817 // Add the system search path to our path.
1818 if (!no_system_path
)
1820 SystemTools::GetPath(path
);
1823 // now add the additional paths
1824 path
.insert(path
.end(), userPaths
.begin(), userPaths
.end());
1826 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
1827 p
!= path
.end(); ++p
)
1832 if(SystemTools::FileExists(tryPath
.c_str()) &&
1833 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1835 return SystemTools::CollapseFullPath(tryPath
.c_str());
1839 if(SystemTools::FileExists(tryPath
.c_str()) &&
1840 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1842 return SystemTools::CollapseFullPath(tryPath
.c_str());
1848 tryPath
+= SystemTools::GetExecutableExtension();
1849 if(SystemTools::FileExists(tryPath
.c_str()) &&
1850 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1852 return SystemTools::CollapseFullPath(tryPath
.c_str());
1856 // Couldn't find the program.
1862 * Find the library with the given name. Searches the given path and then
1863 * the system search path. Returns the full path to the library if it is
1864 * found. Otherwise, the empty string is returned.
1866 kwsys_stl::string SystemTools
1867 ::FindLibrary(const char* name
,
1868 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
)
1870 // See if the executable exists as written.
1871 if(SystemTools::FileExists(name
) &&
1872 !SystemTools::FileIsDirectory(name
))
1874 return SystemTools::CollapseFullPath(name
);
1877 // Add the system search path to our path.
1878 kwsys_stl::vector
<kwsys_stl::string
> path
;
1879 SystemTools::GetPath(path
);
1880 // now add the additional paths
1881 path
.insert(path
.end(), userPaths
.begin(), userPaths
.end());
1882 kwsys_stl::string tryPath
;
1883 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
1884 p
!= path
.end(); ++p
)
1886 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
1891 if(SystemTools::FileExists(tryPath
.c_str())
1892 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1894 return SystemTools::CollapseFullPath(tryPath
.c_str());
1901 if(SystemTools::FileExists(tryPath
.c_str())
1902 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1904 return SystemTools::CollapseFullPath(tryPath
.c_str());
1910 if(SystemTools::FileExists(tryPath
.c_str())
1911 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1913 return SystemTools::CollapseFullPath(tryPath
.c_str());
1919 if(SystemTools::FileExists(tryPath
.c_str())
1920 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1922 return SystemTools::CollapseFullPath(tryPath
.c_str());
1927 tryPath
+= ".dylib";
1928 if(SystemTools::FileExists(tryPath
.c_str())
1929 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1931 return SystemTools::CollapseFullPath(tryPath
.c_str());
1937 if(SystemTools::FileExists(tryPath
.c_str())
1938 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1940 return SystemTools::CollapseFullPath(tryPath
.c_str());
1945 // Couldn't find the library.
1949 bool SystemTools::FileIsDirectory(const char* name
)
1952 if(stat(name
, &fs
) == 0)
1955 return ((fs
.st_mode
& _S_IFDIR
) != 0);
1957 return S_ISDIR(fs
.st_mode
);
1966 int SystemTools::ChangeDirectory(const char *dir
)
1971 kwsys_stl::string
SystemTools::GetCurrentWorkingDirectory()
1974 const char* cwd
= Getcwd(buf
, 2048);
1975 kwsys_stl::string path
;
1981 return SystemTools::CollapseFullPath(path
.c_str());
1984 kwsys_stl::string
SystemTools::GetProgramPath(const char* in_name
)
1986 kwsys_stl::string dir
, file
;
1987 SystemTools::SplitProgramPath(in_name
, dir
, file
);
1991 bool SystemTools::SplitProgramPath(const char* in_name
,
1992 kwsys_stl::string
& dir
,
1993 kwsys_stl::string
& file
,
1998 SystemTools::ConvertToUnixSlashes(dir
);
2000 if(!SystemTools::FileIsDirectory(dir
.c_str()))
2002 kwsys_stl::string::size_type slashPos
= dir
.rfind("/");
2003 if(slashPos
!= kwsys_stl::string::npos
)
2005 file
= dir
.substr(slashPos
+1);
2006 dir
= dir
.substr(0, slashPos
);
2014 if(!(dir
== "") && !SystemTools::FileIsDirectory(dir
.c_str()))
2016 kwsys_stl::string oldDir
= in_name
;
2017 SystemTools::ConvertToUnixSlashes(oldDir
);
2024 bool SystemTools::FindProgramPath(const char* argv0
,
2025 kwsys_stl::string
& pathOut
,
2026 kwsys_stl::string
& errorMsg
,
2027 const char* exeName
,
2028 const char* buildDir
,
2029 const char* installPrefix
)
2031 kwsys_stl::vector
<kwsys_stl::string
> failures
;
2032 kwsys_stl::string self
= argv0
;
2033 SystemTools::ConvertToUnixSlashes(self
);
2034 failures
.push_back(argv0
);
2035 self
= SystemTools::FindProgram(self
.c_str());
2036 if(!SystemTools::FileExists(self
.c_str()))
2040 kwsys_stl::string intdir
= ".";
2042 intdir
= CMAKE_INTDIR
;
2049 self
+= SystemTools::GetExecutableExtension();
2054 if(!SystemTools::FileExists(self
.c_str()))
2056 failures
.push_back(self
);
2057 self
= installPrefix
;
2062 if(!SystemTools::FileExists(self
.c_str()))
2064 failures
.push_back(self
);
2065 kwsys_ios::ostringstream msg
;
2066 msg
<< "Can not find the command line program " << exeName
<< "\n";
2067 msg
<< " argv[0] = \"" << argv0
<< "\"\n";
2068 msg
<< " Attempted paths:\n";
2069 kwsys_stl::vector
<kwsys_stl::string
>::iterator i
;
2070 for(i
=failures
.begin(); i
!= failures
.end(); ++i
)
2072 msg
<< " \"" << i
->c_str() << "\"\n";
2074 errorMsg
= msg
.str();
2082 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_relative
)
2084 return SystemTools::CollapseFullPath(in_relative
, 0);
2087 void SystemTools::AddTranslationPath(const char * a
, const char * b
)
2089 kwsys_stl::string path_a
= a
;
2090 kwsys_stl::string path_b
= b
;
2091 SystemTools::ConvertToUnixSlashes(path_a
);
2092 SystemTools::ConvertToUnixSlashes(path_b
);
2093 // First check this is a directory path, since we don't want the table to
2095 if( SystemTools::FileIsDirectory( path_a
.c_str() ) )
2097 // Make sure the path is a full path and does not contain no '..'
2098 if( SystemTools::FileIsFullPath(path_b
.c_str()) && path_b
.find("..")
2099 == kwsys_stl::string::npos
)
2101 // Before inserting make sure path ends with '/'
2102 if(path_a
.size() && path_a
[path_a
.size() -1] != '/')
2106 if(path_b
.size() && path_b
[path_b
.size() -1] != '/')
2110 if( !(path_a
== path_b
) )
2112 SystemTools::TranslationMap
->insert(
2113 SystemToolsTranslationMap::value_type(path_a
, path_b
));
2119 void SystemTools::AddKeepPath(const char* dir
)
2121 kwsys_stl::string cdir
= SystemTools::CollapseFullPath(dir
);
2122 SystemTools::AddTranslationPath(cdir
.c_str(), dir
);
2125 void SystemTools::CheckTranslationPath(kwsys_stl::string
& path
)
2127 // Do not translate paths that are too short to have meaningful
2134 // Always add a trailing slash before translation. It does not
2135 // matter if this adds an extra slash, but we do not want to
2136 // translate part of a directory (like the foo part of foo-dir).
2139 // In case a file was specified we still have to go through this:
2140 // Now convert any path found in the table back to the one desired:
2141 kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>::const_iterator it
;
2142 for(it
= SystemTools::TranslationMap
->begin();
2143 it
!= SystemTools::TranslationMap
->end();
2146 // We need to check of the path is a substring of the other path
2147 if(path
.find( it
->first
) == 0)
2149 path
= path
.replace( 0, it
->first
.size(), it
->second
);
2153 // Remove the trailing slash we added before.
2154 path
.erase(path
.end()-1, path
.end());
2158 SystemToolsAppendComponents(
2159 kwsys_stl::vector
<kwsys_stl::string
>& out_components
,
2160 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator first
,
2161 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator last
)
2163 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= first
;
2168 if(out_components
.begin() != out_components
.end())
2170 out_components
.erase(out_components
.end()-1, out_components
.end());
2173 else if(*i
!= "." && *i
!= "")
2175 out_components
.push_back(*i
);
2180 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_path
,
2181 const char* in_base
)
2183 // Collect the output path components.
2184 kwsys_stl::vector
<kwsys_stl::string
> out_components
;
2186 // Split the input path components.
2187 kwsys_stl::vector
<kwsys_stl::string
> path_components
;
2188 SystemTools::SplitPath(in_path
, path_components
);
2190 // If the input path is relative, start with a base path.
2191 if(path_components
[0].length() == 0)
2193 kwsys_stl::vector
<kwsys_stl::string
> base_components
;
2196 // Use the given base path.
2197 SystemTools::SplitPath(in_base
, base_components
);
2201 // Use the current working directory as a base path.
2203 if(const char* cwd
= Getcwd(buf
, 2048))
2205 SystemTools::SplitPath(cwd
, base_components
);
2213 // Append base path components to the output path.
2214 out_components
.push_back(base_components
[0]);
2215 SystemToolsAppendComponents(out_components
,
2216 base_components
.begin()+1,
2217 base_components
.end());
2220 // Append input path components to the output path.
2221 SystemToolsAppendComponents(out_components
,
2222 path_components
.begin(),
2223 path_components
.end());
2225 // Transform the path back to a string.
2226 kwsys_stl::string newPath
= SystemTools::JoinPath(out_components
);
2228 // Update the translation table with this potentially new path.
2229 SystemTools::AddTranslationPath(newPath
.c_str(), in_path
);
2230 SystemTools::CheckTranslationPath(newPath
);
2232 // Return the reconstructed path.
2236 //----------------------------------------------------------------------------
2237 void SystemTools::SplitPath(const char* p
,
2238 kwsys_stl::vector
<kwsys_stl::string
>& components
)
2241 // Identify the root component.
2243 if(c
[0] == '/' && c
[1] == '/')
2246 components
.push_back("//");
2249 else if(c
[0] == '/')
2252 components
.push_back("/");
2255 else if(c
[0] && c
[1] == ':' && c
[2] == '/')
2258 kwsys_stl::string root
= "_:/";
2260 components
.push_back(root
);
2263 else if(c
[0] && c
[1] == ':')
2265 // Path relative to a windows drive working directory.
2266 kwsys_stl::string root
= "_:";
2268 components
.push_back(root
);
2274 components
.push_back("");
2277 // Parse the remaining components.
2278 const char* first
= c
;
2279 const char* last
= first
;
2284 // End of a component. Save it.
2285 components
.push_back(kwsys_stl::string(first
, last
-first
));
2290 // Save the last component unless there were no components.
2293 components
.push_back(kwsys_stl::string(first
, last
-first
));
2297 //----------------------------------------------------------------------------
2299 SystemTools::JoinPath(const kwsys_stl::vector
<kwsys_stl::string
>& components
)
2301 kwsys_stl::string result
;
2302 if(components
.size() > 0)
2304 result
+= components
[0];
2306 if(components
.size() > 1)
2308 result
+= components
[1];
2310 for(unsigned int i
=2; i
< components
.size(); ++i
)
2313 result
+= components
[i
];
2318 //----------------------------------------------------------------------------
2319 bool SystemTools::ComparePath(const char* c1
, const char* c2
)
2321 #if defined(_WIN32) || defined(__APPLE__)
2322 return SystemTools::Strucmp(c1
, c2
) == 0;
2324 return strcmp(c1
, c2
) == 0;
2328 bool SystemTools::Split(const char* str
, kwsys_stl::vector
<kwsys_stl::string
>& lines
)
2330 kwsys_stl::string
data(str
);
2331 kwsys_stl::string::size_type lpos
= 0;
2332 while(lpos
< data
.length())
2334 kwsys_stl::string::size_type rpos
= data
.find_first_of("\n", lpos
);
2335 if(rpos
== kwsys_stl::string::npos
)
2337 // Line ends at end of string without a newline.
2338 lines
.push_back(data
.substr(lpos
));
2341 if((rpos
> lpos
) && (data
[rpos
-1] == '\r'))
2343 // Line ends in a "\r\n" pair, remove both characters.
2344 lines
.push_back(data
.substr(lpos
, (rpos
-1)-lpos
));
2348 // Line ends in a "\n", remove the character.
2349 lines
.push_back(data
.substr(lpos
, rpos
-lpos
));
2357 * Return path of a full filename (no trailing slashes).
2358 * Warning: returned path is converted to Unix slashes format.
2360 kwsys_stl::string
SystemTools::GetFilenamePath(const kwsys_stl::string
& filename
)
2362 kwsys_stl::string fn
= filename
;
2363 SystemTools::ConvertToUnixSlashes(fn
);
2365 kwsys_stl::string::size_type slash_pos
= fn
.rfind("/");
2366 if(slash_pos
!= kwsys_stl::string::npos
)
2368 return fn
.substr(0, slash_pos
);
2378 * Return file name of a full filename (i.e. file name without path).
2380 kwsys_stl::string
SystemTools::GetFilenameName(const kwsys_stl::string
& filename
)
2382 kwsys_stl::string fn
= filename
;
2383 SystemTools::ConvertToUnixSlashes(fn
);
2385 kwsys_stl::string::size_type slash_pos
= fn
.rfind("/");
2386 if(slash_pos
!= kwsys_stl::string::npos
)
2388 return fn
.substr(slash_pos
+ 1);
2398 * Return file extension of a full filename (dot included).
2399 * Warning: this is the longest extension (for example: .tar.gz)
2401 kwsys_stl::string
SystemTools::GetFilenameExtension(const kwsys_stl::string
& filename
)
2403 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2404 kwsys_stl::string::size_type dot_pos
= name
.find(".");
2405 if(dot_pos
!= kwsys_stl::string::npos
)
2407 return name
.substr(dot_pos
);
2416 * Return file extension of a full filename (dot included).
2417 * Warning: this is the shortest extension (for example: .tar.gz)
2419 kwsys_stl::string
SystemTools::GetFilenameLastExtension(const kwsys_stl::string
& filename
)
2421 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2422 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
2423 if(dot_pos
!= kwsys_stl::string::npos
)
2425 return name
.substr(dot_pos
);
2434 * Return file name without extension of a full filename (i.e. without path).
2435 * Warning: it considers the longest extension (for example: .tar.gz)
2437 kwsys_stl::string
SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string
& filename
)
2439 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2440 kwsys_stl::string::size_type dot_pos
= name
.find(".");
2441 if(dot_pos
!= kwsys_stl::string::npos
)
2443 return name
.substr(0, dot_pos
);
2453 * Return file name without extension of a full filename (i.e. without path).
2454 * Warning: it considers the last extension (for example: removes .gz
2458 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string
& filename
)
2460 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2461 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
2462 if(dot_pos
!= kwsys_stl::string::npos
)
2464 return name
.substr(0, dot_pos
);
2472 bool SystemTools::FileHasSignature(const char *filename
,
2473 const char *signature
,
2476 if (!filename
|| !signature
)
2482 fp
= fopen(filename
, "rb");
2488 fseek(fp
, offset
, SEEK_SET
);
2491 size_t signature_len
= strlen(signature
);
2492 char *buffer
= new char [signature_len
];
2494 if (fread(buffer
, 1, signature_len
, fp
) == signature_len
)
2496 res
= (!strncmp(buffer
, signature
, signature_len
) ? true : false);
2505 bool SystemTools::LocateFileInDir(const char *filename
,
2507 kwsys_stl::string
& filename_found
,
2508 int try_filename_dirs
)
2510 if (!filename
|| !dir
)
2515 // Get the basename of 'filename'
2517 kwsys_stl::string filename_base
= SystemTools::GetFilenameName(filename
);
2519 // Check if 'dir' is really a directory
2520 // If win32 and matches something like C:, accept it as a dir
2522 kwsys_stl::string real_dir
;
2523 if (!SystemTools::FileIsDirectory(dir
))
2526 size_t dir_len
= strlen(dir
);
2527 if (dir_len
< 2 || dir
[dir_len
- 1] != ':')
2530 real_dir
= SystemTools::GetFilenamePath(dir
);
2531 dir
= real_dir
.c_str();
2537 // Try to find the file in 'dir'
2540 if (filename_base
.size() && dir
)
2542 size_t dir_len
= strlen(dir
);
2544 (dir_len
&& dir
[dir_len
- 1] != '/' && dir
[dir_len
- 1] != '\\');
2546 kwsys_stl::string temp
= dir
;
2551 temp
+= filename_base
;
2553 if (SystemTools::FileExists(filename_found
.c_str()))
2556 filename_found
= temp
;
2559 // If not found, we can try harder by appending part of the file to
2560 // to the directory to look inside.
2561 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
2562 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
2564 else if (try_filename_dirs
)
2566 kwsys_stl::string
filename_dir(filename
);
2567 kwsys_stl::string filename_dir_base
;
2568 kwsys_stl::string filename_dir_bases
;
2571 filename_dir
= SystemTools::GetFilenamePath(filename_dir
);
2572 filename_dir_base
= SystemTools::GetFilenameName(filename_dir
);
2574 if (!filename_dir_base
.size() ||
2575 filename_dir_base
[filename_dir_base
.size() - 1] == ':')
2577 if (!filename_dir_base
.size())
2583 filename_dir_bases
= filename_dir_base
+ "/" + filename_dir_bases
;
2590 temp
+= filename_dir_bases
;
2592 res
= SystemTools::LocateFileInDir(
2593 filename_base
.c_str(), temp
.c_str(), filename_found
, 0);
2595 } while (!res
&& filename_dir_base
.size());
2602 bool SystemTools::FileIsFullPath(const char* in_name
)
2604 kwsys_stl::string name
= in_name
;
2605 #if defined(_WIN32) || defined(__CYGWIN__)
2606 // On Windows, the name must be at least two characters long.
2607 if(name
.length() < 2)
2620 // On UNIX, the name must be at least one character long.
2621 if(name
.length() < 1)
2626 // On UNIX, the name must begin in a '/'.
2627 // On Windows, if the name begins in a '/', then it is a full
2636 bool SystemTools::GetShortPath(const char* path
, kwsys_stl::string
& shortPath
)
2638 #if defined(WIN32) && !defined(__CYGWIN__)
2639 const int size
= int(strlen(path
)) +1; // size of return
2640 char *buffer
= new char[size
]; // create a buffer
2641 char *tempPath
= new char[size
]; // create a buffer
2644 // if the path passed in has quotes around it, first remove the quotes
2645 if (path
[0] == '"' && path
[strlen(path
)-1] == '"')
2647 strcpy(tempPath
,path
+1);
2648 tempPath
[strlen(tempPath
)-1] = '\0';
2652 strcpy(tempPath
,path
);
2656 ret
= GetShortPathName(tempPath
, buffer
, size
);
2658 if(buffer
[0] == 0 || ret
> size
)
2677 void SystemTools::SplitProgramFromArgs(const char* path
,
2678 kwsys_stl::string
& program
, kwsys_stl::string
& args
)
2680 // see if this is a full path to a program
2681 // if so then set program to path and args to nothing
2682 if(SystemTools::FileExists(path
))
2688 // Try to find the program in the path, note the program
2689 // may have spaces in its name so we have to look for it
2690 kwsys_stl::vector
<kwsys_stl::string
> e
;
2691 kwsys_stl::string findProg
= SystemTools::FindProgram(path
, e
);
2699 // Now try and peel off space separated chunks from the end of the string
2700 // so the largest path possible is found allowing for spaces in the path
2701 kwsys_stl::string dir
= path
;
2702 kwsys_stl::string::size_type spacePos
= dir
.rfind(' ');
2703 while(spacePos
!= kwsys_stl::string::npos
)
2705 kwsys_stl::string tryProg
= dir
.substr(0, spacePos
);
2706 // See if the file exists
2707 if(SystemTools::FileExists(tryProg
.c_str()))
2710 // remove trailing spaces from program
2711 kwsys_stl::string::size_type pos
= program
.size()-1;
2712 while(program
[pos
] == ' ')
2717 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
2720 // Now try and find the the program in the path
2721 findProg
= SystemTools::FindProgram(tryProg
.c_str(), e
);
2725 // remove trailing spaces from program
2726 kwsys_stl::string::size_type pos
= program
.size()-1;
2727 while(program
[pos
] == ' ')
2732 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
2735 // move past the space for the next search
2737 spacePos
= dir
.rfind(' ', spacePos
);
2744 kwsys_stl::string
SystemTools::GetCurrentDateTime(const char* format
)
2749 strftime(buf
, sizeof(buf
), format
, localtime(&t
));
2753 kwsys_stl::string
SystemTools::MakeCindentifier(const char* s
)
2755 kwsys_stl::string
str(s
);
2756 if (str
.find_first_of("0123456789") == 0)
2761 kwsys_stl::string
permited_chars("_"
2762 "abcdefghijklmnopqrstuvwxyz"
2763 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2765 kwsys_stl::string::size_type pos
= 0;
2766 while ((pos
= str
.find_first_not_of(permited_chars
, pos
)) != kwsys_stl::string::npos
)
2773 // Due to a buggy stream library on the HP and another on Mac OSX, we
2774 // need this very carefully written version of getline. Returns true
2775 // if any data were read before the end-of-file was reached.
2776 bool SystemTools::GetLineFromStream(kwsys_ios::istream
& is
, kwsys_stl::string
& line
,
2777 bool *has_newline
/* = 0 */)
2779 const int bufferSize
= 1024;
2780 char buffer
[bufferSize
];
2782 bool haveData
= false;
2785 *has_newline
= false;
2788 // If no characters are read from the stream, the end of file has
2790 while((is
.getline(buffer
, bufferSize
), is
.gcount() > 0))
2793 line
.append(buffer
);
2795 // If newline character was read, the gcount includes the
2796 // character, but the buffer does not. The end of line has been
2798 if(strlen(buffer
) < static_cast<size_t>(is
.gcount()))
2802 *has_newline
= true;
2807 // The fail bit may be set. Clear it.
2808 is
.clear(is
.rdstate() & ~kwsys_ios::ios::failbit
);
2813 int SystemTools::GetTerminalWidth()
2818 char *columns
; /* Unix98 environment variable */
2819 if(ioctl(1, TIOCGWINSZ
, &ws
) != -1 && ws
.ws_col
>0 && ws
.ws_row
>0)
2823 if(!isatty(STDOUT_FILENO
))
2827 columns
= getenv("COLUMNS");
2828 if(columns
&& *columns
)
2832 t
= strtol(columns
, &endptr
, 0);
2833 if(endptr
&& !*endptr
&& (t
>0) && (t
<1000))
2846 bool SystemTools::GetPermissions(const char* file
, mode_t
& mode
)
2854 if ( stat(file
, &st
) < 0 )
2862 bool SystemTools::SetPermissions(const char* file
, mode_t mode
)
2868 if ( !SystemTools::FileExists(file
) )
2872 if ( chmod(file
, mode
) < 0 )
2880 kwsys_stl::string
SystemTools::GetParentDirectory(const char* fileOrDir
)
2882 if ( !fileOrDir
|| !*fileOrDir
)
2886 kwsys_stl::string res
= fileOrDir
;
2887 SystemTools::ConvertToUnixSlashes(res
);
2888 kwsys_stl::string::size_type cc
= res
.size()-1;
2889 if ( res
[cc
] == '/' )
2893 for ( ; cc
> 0; cc
-- )
2895 if ( res
[cc
] == '/' )
2900 return res
.substr(0, cc
);
2903 bool SystemTools::IsSubDirectory(const char* cSubdir
, const char* cDir
)
2905 kwsys_stl::string subdir
= cSubdir
;
2906 kwsys_stl::string dir
= cDir
;
2907 SystemTools::ConvertToUnixSlashes(dir
);
2908 kwsys_stl::string path
= subdir
;
2911 path
= SystemTools::GetParentDirectory(path
.c_str());
2917 while ( path
.size() > dir
.size() );
2921 kwsys_stl::string
SystemTools::FileExistsInParentDirectories(const char* fname
,
2922 const char* directory
, const char* toplevel
)
2924 kwsys_stl::string file
= fname
;
2925 SystemTools::ConvertToUnixSlashes(file
);
2926 kwsys_stl::string dir
= directory
;
2927 SystemTools::ConvertToUnixSlashes(dir
);
2928 while ( !dir
.empty() )
2930 kwsys_stl::string path
= dir
+ "/" + file
;
2931 if ( SystemTools::FileExists(path
.c_str()) )
2935 if ( dir
.size() < strlen(toplevel
) )
2939 dir
= SystemTools::GetParentDirectory(dir
.c_str());
2944 void SystemTools::Delay(unsigned int msec
)
2949 usleep(msec
* 1000);
2953 // These must NOT be initialized. Default initialization to zero is
2955 unsigned int SystemToolsManagerCount
;
2956 SystemToolsTranslationMap
*SystemTools::TranslationMap
;
2958 // SystemToolsManager manages the SystemTools singleton.
2959 // SystemToolsManager should be included in any translation unit
2960 // that will use SystemTools or that implements the singleton
2961 // pattern. It makes sure that the SystemTools singleton is created
2962 // before and destroyed after all other singletons in CMake.
2964 SystemToolsManager::SystemToolsManager()
2966 if(++SystemToolsManagerCount
== 1)
2968 SystemTools::ClassInitialize();
2972 SystemToolsManager::~SystemToolsManager()
2974 if(--SystemToolsManagerCount
== 0)
2976 SystemTools::ClassFinalize();
2980 void SystemTools::ClassInitialize()
2982 // Allocate the translation map first.
2983 SystemTools::TranslationMap
= new SystemToolsTranslationMap
;
2985 // Add some special translation paths for unix. These are not added
2986 // for windows because drive letters need to be maintained. Also,
2987 // there are not sym-links and mount points on windows anyway.
2988 #if !defined(_WIN32) || defined(__CYGWIN__)
2989 // Work-around an SGI problem by always adding this mapping:
2990 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
2991 // The tmp path is frequently a logical path so always keep it:
2992 SystemTools::AddKeepPath("/tmp/");
2994 // If the current working directory is a logical path then keep the
2996 if(const char* pwd
= getenv("PWD"))
2999 if(const char* cwd
= Getcwd(buf
, 2048))
3001 kwsys_stl::string pwd_path
;
3002 Realpath(pwd
, pwd_path
);
3003 if(cwd
== pwd_path
&& strcmp(cwd
, pwd
) != 0)
3005 // The current working directory is a logical path. Split
3006 // both the logical and physical paths into their components.
3007 kwsys_stl::vector
<kwsys_stl::string
> cwd_components
;
3008 kwsys_stl::vector
<kwsys_stl::string
> pwd_components
;
3009 SystemTools::SplitPath(cwd
, cwd_components
);
3010 SystemTools::SplitPath(pwd
, pwd_components
);
3012 // Remove the common ending of the paths to leave only the
3013 // part that changes under the logical mapping.
3014 kwsys_stl::vector
<kwsys_stl::string
>::iterator ic
= cwd_components
.end();
3015 kwsys_stl::vector
<kwsys_stl::string
>::iterator ip
= pwd_components
.end();
3016 for(;ip
!= pwd_components
.begin() && ic
!= cwd_components
.begin() &&
3017 *(ip
-1) == *(ic
-1); --ip
,--ic
);
3018 cwd_components
.erase(ic
, cwd_components
.end());
3019 pwd_components
.erase(ip
, pwd_components
.end());
3021 // Reconstruct the string versions of the part of the path
3023 kwsys_stl::string cwd_changed
= SystemTools::JoinPath(cwd_components
);
3024 kwsys_stl::string pwd_changed
= SystemTools::JoinPath(pwd_components
);
3026 // Add the translation to keep the logical path name.
3027 if(!cwd_changed
.empty() && !pwd_changed
.empty())
3029 SystemTools::AddTranslationPath(cwd_changed
.c_str(),
3030 pwd_changed
.c_str());
3038 void SystemTools::ClassFinalize()
3040 delete SystemTools::TranslationMap
;
3044 } // namespace KWSYS_NAMESPACE
3046 #if defined(_MSC_VER) && defined(_DEBUG)
3047 # include <crtdbg.h>
3049 # include <stdlib.h>
3050 namespace KWSYS_NAMESPACE
3053 static int SystemToolsDebugReport(int, char* message
, int*)
3055 fprintf(stderr
, message
);
3058 void SystemTools::EnableMSVCDebugHook()
3060 if(getenv("DART_TEST_FROM_DART"))
3062 _CrtSetReportHook(SystemToolsDebugReport
);
3066 } // namespace KWSYS_NAMESPACE
3068 namespace KWSYS_NAMESPACE
3070 void SystemTools::EnableMSVCDebugHook() {}
3071 } // namespace KWSYS_NAMESPACE