1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmSystemTools.cxx,v $
6 Date: $Date: 2009-02-05 21:31:34 $
7 Version: $Revision: 1.389 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmSystemTools.h"
23 #include <cmsys/RegularExpression.hxx>
24 #include <cmsys/Directory.hxx>
25 #include <cmsys/System.h>
26 #if defined(CMAKE_BUILD_WITH_CMAKE)
27 # include <cmsys/Terminal.h>
29 #include <cmsys/stl/algorithm>
34 # include <sys/types.h>
37 # include <sys/wait.h>
42 #if defined(_WIN32) && \
43 (defined(_MSC_VER) || defined(__WATCOMC__) || \
44 defined(__BORLANDC__) || defined(__MINGW32__))
48 #if defined(CMAKE_BUILD_WITH_CMAKE)
49 # include <libtar/libtar.h>
50 # include <memory> // auto_ptr
53 # include <cmsys/MD5.h>
56 #if defined(CMAKE_USE_ELF_PARSER)
60 class cmSystemToolsFileTime
63 #if defined(_WIN32) && !defined(__CYGWIN__)
64 FILETIME timeCreation
;
65 FILETIME timeLastAccess
;
66 FILETIME timeLastWrite
;
68 struct utimbuf timeBuf
;
72 #if defined(__sgi) && !defined(__GNUC__)
73 # pragma set woff 1375 /* base class destructor not virtual */
76 #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
77 // For GetEnvironmentVariables
79 extern __declspec( dllimport
) char** environ
;
81 extern char** environ
;
86 class cmSystemToolsWindowsHandle
89 cmSystemToolsWindowsHandle(HANDLE h
): handle_(h
) {}
90 ~cmSystemToolsWindowsHandle()
92 if(this->handle_
!= INVALID_HANDLE_VALUE
)
94 CloseHandle(this->handle_
);
97 operator bool() const { return this->handle_
!= INVALID_HANDLE_VALUE
; }
98 bool operator !() const { return this->handle_
== INVALID_HANDLE_VALUE
; }
99 operator HANDLE() const { return this->handle_
; }
105 bool cmSystemTools::s_RunCommandHideConsole
= false;
106 bool cmSystemTools::s_DisableRunCommandOutput
= false;
107 bool cmSystemTools::s_ErrorOccured
= false;
108 bool cmSystemTools::s_FatalErrorOccured
= false;
109 bool cmSystemTools::s_DisableMessages
= false;
110 bool cmSystemTools::s_ForceUnixPaths
= false;
112 std::string
cmSystemTools::s_Windows9xComspecSubstitute
= "command.com";
113 void cmSystemTools::SetWindows9xComspecSubstitute(const char* str
)
117 cmSystemTools::s_Windows9xComspecSubstitute
= str
;
120 const char* cmSystemTools::GetWindows9xComspecSubstitute()
122 return cmSystemTools::s_Windows9xComspecSubstitute
.c_str();
125 void (*cmSystemTools::s_ErrorCallback
)(const char*, const char*,
127 void (*cmSystemTools::s_StdoutCallback
)(const char*, int len
, void*);
128 void* cmSystemTools::s_ErrorCallbackClientData
= 0;
129 void* cmSystemTools::s_StdoutCallbackClientData
= 0;
131 // replace replace with with as many times as it shows up in source.
132 // write the result into source.
133 #if defined(_WIN32) && !defined(__CYGWIN__)
134 void cmSystemTools::ExpandRegistryValues(std::string
& source
, KeyWOW64 view
)
136 // Regular expression to match anything inside [...] that begins in HKEY.
137 // Note that there is a special rule for regular expressions to match a
138 // close square-bracket inside a list delimited by square brackets.
139 // The "[^]]" part of this expression will match any character except
140 // a close square-bracket. The ']' character must be the first in the
141 // list of characters inside the [^...] block of the expression.
142 cmsys::RegularExpression
regEntry("\\[(HKEY[^]]*)\\]");
144 // check for black line or comment
145 while (regEntry
.find(source
))
147 // the arguments are the second match
148 std::string key
= regEntry
.match(1);
150 if (ReadRegistryValue(key
.c_str(), val
, view
))
152 std::string reg
= "[";
154 cmSystemTools::ReplaceString(source
, reg
.c_str(), val
.c_str());
158 std::string reg
= "[";
160 cmSystemTools::ReplaceString(source
, reg
.c_str(), "/registry");
165 void cmSystemTools::ExpandRegistryValues(std::string
& source
, KeyWOW64
)
167 cmsys::RegularExpression
regEntry("\\[(HKEY[^]]*)\\]");
168 while (regEntry
.find(source
))
170 // the arguments are the second match
171 std::string key
= regEntry
.match(1);
173 std::string reg
= "[";
175 cmSystemTools::ReplaceString(source
, reg
.c_str(), "/registry");
181 std::string
cmSystemTools::EscapeQuotes(const char* str
)
183 std::string result
= "";
184 for(const char* ch
= str
; *ch
!= '\0'; ++ch
)
195 std::string
cmSystemTools::EscapeSpaces(const char* str
)
197 #if defined(_WIN32) && !defined(__CYGWIN__)
198 bool useDoubleQ
= true;
200 bool useDoubleQ
= false;
202 if(cmSystemTools::s_ForceUnixPaths
)
211 // if there are spaces
212 std::string temp
= str
;
213 if (temp
.find(" ") != std::string::npos
&&
214 temp
.find("\"")==std::string::npos
)
225 std::string result
= "";
226 for(const char* ch
= str
; *ch
!= '\0'; ++ch
)
239 std::string
cmSystemTools::RemoveEscapes(const char* s
)
241 std::string result
= "";
242 for(const char* ch
= s
; *ch
; ++ch
)
244 if(*ch
== '\\' && *(ch
+1) != ';')
249 case '\\': result
.insert(result
.end(), '\\'); break;
250 case '"': result
.insert(result
.end(), '"'); break;
251 case ' ': result
.insert(result
.end(), ' '); break;
252 case 't': result
.insert(result
.end(), '\t'); break;
253 case 'n': result
.insert(result
.end(), '\n'); break;
254 case 'r': result
.insert(result
.end(), '\r'); break;
255 case '#': result
.insert(result
.end(), '#'); break;
256 case '(': result
.insert(result
.end(), '('); break;
257 case ')': result
.insert(result
.end(), ')'); break;
258 case '0': result
.insert(result
.end(), '\0'); break;
261 cmSystemTools::Error("Trailing backslash in argument:\n", s
);
266 std::string
chStr(1, *ch
);
267 cmSystemTools::Error("Invalid escape sequence \\", chStr
.c_str(),
268 "\nin argument ", s
);
274 result
.insert(result
.end(), *ch
);
280 void cmSystemTools::Error(const char* m1
, const char* m2
,
281 const char* m3
, const char* m4
)
283 std::string message
= "CMake Error: ";
300 cmSystemTools::s_ErrorOccured
= true;
301 cmSystemTools::Message(message
.c_str(),"Error");
305 void cmSystemTools::SetErrorCallback(ErrorCallback f
, void* clientData
)
308 s_ErrorCallbackClientData
= clientData
;
311 void cmSystemTools::SetStdoutCallback(StdoutCallback f
, void* clientData
)
313 s_StdoutCallback
= f
;
314 s_StdoutCallbackClientData
= clientData
;
317 void cmSystemTools::Stdout(const char* s
)
321 (*s_StdoutCallback
)(s
, static_cast<int>(strlen(s
)),
322 s_StdoutCallbackClientData
);
331 void cmSystemTools::Stdout(const char* s
, int length
)
335 (*s_StdoutCallback
)(s
, length
, s_StdoutCallbackClientData
);
339 std::cout
.write(s
, length
);
344 void cmSystemTools::Message(const char* m1
, const char *title
)
346 if(s_DisableMessages
)
352 (*s_ErrorCallback
)(m1
, title
, s_DisableMessages
,
353 s_ErrorCallbackClientData
);
358 std::cerr
<< m1
<< std::endl
<< std::flush
;
364 void cmSystemTools::ReportLastSystemError(const char* msg
)
367 m
+= ": System Error: ";
368 m
+= Superclass::GetLastSystemError();
369 cmSystemTools::Error(m
.c_str());
373 bool cmSystemTools::IsOn(const char* val
)
379 std::basic_string
<char> v
= val
;
381 for(std::basic_string
<char>::iterator c
= v
.begin();
386 return (v
== "ON" || v
== "1" || v
== "YES" || v
== "TRUE" || v
== "Y");
389 bool cmSystemTools::IsNOTFOUND(const char* val
)
391 size_t len
= strlen(val
);
392 const char* notfound
= "-NOTFOUND";
393 const size_t lenNotFound
= 9;
394 if(len
< lenNotFound
-1)
398 if(len
== lenNotFound
-1)
400 return ( strcmp(val
, "NOTFOUND") == 0);
402 return ((strncmp((val
+ (len
- lenNotFound
)), notfound
, lenNotFound
) == 0));
406 bool cmSystemTools::IsOff(const char* val
)
408 if (!val
|| strlen(val
) == 0)
412 std::basic_string
<char> v
= val
;
414 for(std::basic_string
<char>::iterator c
= v
.begin();
419 return (v
== "OFF" || v
== "0" || v
== "NO" || v
== "FALSE" ||
420 v
== "N" || cmSystemTools::IsNOTFOUND(v
.c_str()) || v
== "IGNORE");
423 //----------------------------------------------------------------------------
424 void cmSystemTools::ParseWindowsCommandLine(const char* command
,
425 std::vector
<std::string
>& args
)
427 // See the MSDN document "Parsing C Command-Line Arguments" at
428 // http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx for rules
429 // of parsing the windows command line.
431 bool in_argument
= false;
432 bool in_quotes
= false;
435 for(const char* c
= command
;*c
; ++c
)
444 int backslash_pairs
= backslashes
>> 1;
445 int backslash_escaped
= backslashes
& 1;
446 arg
.append(backslash_pairs
, '\\');
448 if(backslash_escaped
)
450 /* An odd number of backslashes precede this quote.
456 /* An even number of backslashes precede this quote.
457 It is not escaped. */
458 in_quotes
= !in_quotes
;
464 arg
.append(backslashes
, '\\');
486 arg
.append(backslashes
, '\\');
493 std::string
cmSystemTools::EscapeWindowsShellArgument(const char* arg
,
496 char local_buffer
[1024];
497 char* buffer
= local_buffer
;
498 int size
= cmsysSystem_Shell_GetArgumentSizeForWindows(arg
, shell_flags
);
501 buffer
= new char[size
];
503 cmsysSystem_Shell_GetArgumentForWindows(arg
, buffer
, shell_flags
);
504 std::string
result(buffer
);
505 if(buffer
!= local_buffer
)
512 std::vector
<cmStdString
> cmSystemTools::ParseArguments(const char* command
)
514 std::vector
<cmStdString
> args
;
517 bool win_path
= false;
519 if ( command
[0] != '/' && command
[1] == ':' && command
[2] == '\\' ||
520 command
[0] == '\"' && command
[1] != '/' && command
[2] == ':'
521 && command
[3] == '\\' ||
522 command
[0] == '\'' && command
[1] != '/' && command
[2] == ':'
523 && command
[3] == '\\' ||
524 command
[0] == '\\' && command
[1] == '\\')
528 // Split the command into an argv array.
529 for(const char* c
= command
; *c
;)
531 // Skip over whitespace.
532 while(*c
== ' ' || *c
== '\t')
539 // Parse a quoted argument.
541 while(*c
&& *c
!= '"')
554 // Parse a quoted argument.
556 while(*c
&& *c
!= '\'')
569 // Parse an unquoted argument.
570 while(*c
&& *c
!= ' ' && *c
!= '\t')
572 if(*c
== '\\' && !win_path
)
595 bool cmSystemTools::RunSingleCommand(std::vector
<cmStdString
>const& command
,
596 std::string
* output
,
597 int* retVal
, const char* dir
,
601 std::vector
<const char*> argv
;
602 for(std::vector
<cmStdString
>::const_iterator a
= command
.begin();
603 a
!= command
.end(); ++a
)
605 argv
.push_back(a
->c_str());
613 cmsysProcess
* cp
= cmsysProcess_New();
614 cmsysProcess_SetCommand(cp
, &*argv
.begin());
615 cmsysProcess_SetWorkingDirectory(cp
, dir
);
616 if(cmSystemTools::GetRunCommandHideConsole())
618 cmsysProcess_SetOption(cp
, cmsysProcess_Option_HideWindow
, 1);
620 cmsysProcess_SetTimeout(cp
, timeout
);
621 cmsysProcess_Execute(cp
);
623 std::vector
<char> tempOutput
;
626 if ( output
|| verbose
)
628 while(cmsysProcess_WaitForData(cp
, &data
, &length
, 0))
630 if(output
|| verbose
)
632 // Translate NULL characters in the output into valid text.
633 // Visual Studio 7 puts these characters in the output of its
635 for(int i
=0; i
< length
; ++i
)
645 tempOutput
.insert(tempOutput
.end(), data
, data
+length
);
649 cmSystemTools::Stdout(data
, length
);
654 cmsysProcess_WaitForExit(cp
, 0);
655 if ( output
&& tempOutput
.begin() != tempOutput
.end())
657 output
->append(&*tempOutput
.begin(), tempOutput
.size());
661 if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Exited
)
665 *retVal
= cmsysProcess_GetExitValue(cp
);
669 if ( cmsysProcess_GetExitValue(cp
) != 0 )
675 else if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Exception
)
677 const char* exception_str
= cmsysProcess_GetExceptionString(cp
);
680 std::cerr
<< exception_str
<< std::endl
;
684 output
->append(exception_str
, strlen(exception_str
));
688 else if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Error
)
690 const char* error_str
= cmsysProcess_GetErrorString(cp
);
693 std::cerr
<< error_str
<< std::endl
;
697 output
->append(error_str
, strlen(error_str
));
701 else if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Expired
)
703 const char* error_str
= "Process terminated due to timeout\n";
706 std::cerr
<< error_str
<< std::endl
;
710 output
->append(error_str
, strlen(error_str
));
715 cmsysProcess_Delete(cp
);
719 bool cmSystemTools::RunSingleCommand(
727 if(s_DisableRunCommandOutput
)
732 std::vector
<cmStdString
> args
= cmSystemTools::ParseArguments(command
);
738 return cmSystemTools::RunSingleCommand(args
, output
,retVal
,
739 dir
, verbose
, timeout
);
741 bool cmSystemTools::RunCommand(const char* command
,
748 return cmSystemTools::RunCommand(command
, output
, dummy
,
749 dir
, verbose
, timeout
);
752 #if defined(WIN32) && !defined(__CYGWIN__)
753 #include "cmWin32ProcessExecution.h"
754 // use this for shell commands like echo and dir
755 bool RunCommandViaWin32(const char* command
,
762 #if defined(__BORLANDC__)
764 cmWin32ProcessExecution::
765 BorlandRunCommand(command
, dir
, output
,
768 cmSystemTools::GetRunCommandHideConsole());
769 #else // Visual studio
770 ::SetLastError(ERROR_SUCCESS
);
773 cmSystemTools::Error("No command specified");
776 cmWin32ProcessExecution resProc
;
777 if(cmSystemTools::GetRunCommandHideConsole())
779 resProc
.SetHideWindows(true);
782 if ( cmSystemTools::GetWindows9xComspecSubstitute() )
784 resProc
.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
786 if ( !resProc
.StartProcess(command
, dir
, verbose
) )
788 output
= resProc
.GetOutput();
791 cmSystemTools::Stdout(output
.c_str());
795 resProc
.Wait(timeout
);
796 output
= resProc
.GetOutput();
797 retVal
= resProc
.GetExitValue();
802 // use this for shell commands like echo and dir
803 bool RunCommandViaSystem(const char* command
,
809 std::cout
<< "@@ " << command
<< std::endl
;
811 std::string commandInDir
;
814 commandInDir
= "cd ";
815 commandInDir
+= cmSystemTools::ConvertToOutputPath(dir
);
816 commandInDir
+= " && ";
817 commandInDir
+= command
;
821 commandInDir
= command
;
823 command
= commandInDir
.c_str();
824 std::string commandToFile
= command
;
825 commandToFile
+= " > ";
826 std::string tempFile
;
827 tempFile
+= _tempnam(0, "cmake");
829 commandToFile
+= tempFile
;
830 retVal
= system(commandToFile
.c_str());
831 std::ifstream
fin(tempFile
.c_str());
836 std::string errormsg
= "RunCommand produced no output: command: \"";
839 errormsg
+= "\nOutput file: ";
840 errormsg
+= tempFile
;
841 cmSystemTools::Error(errormsg
.c_str());
844 cmSystemTools::RemoveFile(tempFile
.c_str());
847 bool multiLine
= false;
849 while(cmSystemTools::GetLineFromStream(fin
, line
))
859 cmSystemTools::RemoveFile(tempFile
.c_str());
863 #else // We have popen
865 // BeOS seems to return from a successful pclose() before the process has
866 // legitimately exited, or at least before SIGCHLD is thrown...the signal may
867 // come quite some time after pclose returns! This causes havoc with later
868 // parts of CMake that expect to catch the signal from other child processes,
869 // so we explicitly wait to catch it here. This should be safe to do with
870 // popen() so long as we don't actually collect the zombie process ourselves.
873 #undef SIGBUS // this is the same as SIGSEGV on BeOS and causes issues below.
874 static volatile bool beos_seen_signal
= false;
875 static void beos_popen_workaround(int sig
)
877 beos_seen_signal
= true;
881 bool RunCommandViaPopen(const char* command
,
888 // if only popen worked on windows.....
889 std::string commandInDir
;
892 commandInDir
= "cd \"";
894 commandInDir
+= "\" && ";
895 commandInDir
+= command
;
899 commandInDir
= command
;
901 commandInDir
+= " 2>&1";
902 command
= commandInDir
.c_str();
903 const int BUFFER_SIZE
= 4096;
904 char buffer
[BUFFER_SIZE
];
907 cmSystemTools::Stdout("running ");
908 cmSystemTools::Stdout(command
);
909 cmSystemTools::Stdout("\n");
915 beos_seen_signal
= false;
916 signal(SIGCHLD
, beos_popen_workaround
);
919 FILE* cpipe
= popen(command
, "r");
923 signal(SIGCHLD
, SIG_DFL
);
927 fgets(buffer
, BUFFER_SIZE
, cpipe
);
932 cmSystemTools::Stdout(buffer
);
936 fgets(buffer
, BUFFER_SIZE
, cpipe
);
939 retVal
= pclose(cpipe
);
942 for (int i
= 0; (!beos_seen_signal
) && (i
< 3); i
++)
944 ::sleep(1); // signals should interrupt this...
947 if (!beos_seen_signal
)
949 signal(SIGCHLD
, SIG_DFL
); // oh well, didn't happen. Go on anyhow.
953 if (WIFEXITED(retVal
))
955 retVal
= WEXITSTATUS(retVal
);
958 if (WIFSIGNALED(retVal
))
960 retVal
= WTERMSIG(retVal
);
961 cmOStringStream error
;
962 error
<< "\nProcess terminated due to ";
988 error
<< "signal " << retVal
;
991 output
+= error
.str();
996 #endif // endif WIN32 not CYGWIN
999 // run a command unix uses popen (easy)
1000 // windows uses system and ShortPath
1001 bool cmSystemTools::RunCommand(const char* command
,
1002 std::string
& output
,
1008 if(s_DisableRunCommandOutput
)
1013 #if defined(WIN32) && !defined(__CYGWIN__)
1014 // if the command does not start with a quote, then
1015 // try to find the program, and if the program can not be
1016 // found use system to run the command as it must be a built in
1017 // shell command like echo or dir
1019 if(command
[0] == '\"')
1021 // count the number of quotes
1022 for(const char* s
= command
; *s
!= 0; ++s
)
1033 // if there are more than two double quotes use
1034 // GetShortPathName, the cmd.exe program in windows which
1035 // is used by system fails to execute if there are more than
1036 // one set of quotes in the arguments
1039 cmsys::RegularExpression
quoted("^\"([^\"]*)\"[ \t](.*)");
1040 if(quoted
.find(command
))
1042 std::string shortCmd
;
1043 std::string cmd
= quoted
.match(1);
1044 std::string args
= quoted
.match(2);
1045 if(! cmSystemTools::FileExists(cmd
.c_str()) )
1049 else if(!cmSystemTools::GetShortPath(cmd
.c_str(), shortCmd
))
1051 cmSystemTools::Error("GetShortPath failed for " , cmd
.c_str());
1057 //return RunCommandViaSystem(shortCmd.c_str(), dir,
1058 // output, retVal, verbose);
1059 //return WindowsRunCommand(shortCmd.c_str(), dir,
1060 //output, retVal, verbose);
1061 return RunCommandViaWin32(shortCmd
.c_str(), dir
,
1062 output
, retVal
, verbose
, timeout
);
1066 cmSystemTools::Error("Could not parse command line with quotes ",
1071 // if there is only one set of quotes or no quotes then just run the command
1072 //return RunCommandViaSystem(command, dir, output, retVal, verbose);
1073 //return WindowsRunCommand(command, dir, output, retVal, verbose);
1074 return ::RunCommandViaWin32(command
, dir
, output
, retVal
, verbose
, timeout
);
1076 return ::RunCommandViaPopen(command
, dir
, output
, retVal
, verbose
, timeout
);
1080 bool cmSystemTools::DoesFileExistWithExtensions(
1082 const std::vector
<std::string
>& headerExts
)
1086 for( std::vector
<std::string
>::const_iterator ext
= headerExts
.begin();
1087 ext
!= headerExts
.end(); ++ext
)
1092 if(cmSystemTools::FileExists(hname
.c_str()))
1100 bool cmSystemTools::cmCopyFile(const char* source
, const char* destination
)
1102 return Superclass::CopyFileAlways(source
, destination
);
1105 bool cmSystemTools::CopyFileIfDifferent(const char* source
,
1106 const char* destination
)
1108 return Superclass::CopyFileIfDifferent(source
, destination
);
1111 bool cmSystemTools::ComputeFileMD5(const char* source
, char* md5out
)
1113 #if defined(CMAKE_BUILD_WITH_CMAKE)
1114 if(!cmSystemTools::FileExists(source
))
1120 #if defined(_WIN32) || defined(__CYGWIN__)
1121 cmsys_ios::ifstream
fin(source
, cmsys_ios::ios::binary
| cmsys_ios::ios::in
);
1123 cmsys_ios::ifstream
fin(source
);
1130 cmsysMD5
* md5
= cmsysMD5_New();
1131 cmsysMD5_Initialize(md5
);
1133 // Should be efficient enough on most system:
1134 const int bufferSize
= 4096;
1135 char buffer
[bufferSize
];
1136 // This copy loop is very sensitive on certain platforms with
1137 // slightly broken stream libraries (like HPUX). Normally, it is
1138 // incorrect to not check the error condition on the fin.read()
1139 // before using the data, but the fin.gcount() will be zero if an
1140 // error occurred. Therefore, the loop should be safe everywhere.
1143 fin
.read(buffer
, bufferSize
);
1146 cmsysMD5_Append(md5
, reinterpret_cast<unsigned char const*>(buffer
),
1150 cmsysMD5_FinalizeHex(md5
, md5out
);
1151 cmsysMD5_Delete(md5
);
1158 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1163 std::string
cmSystemTools::ComputeStringMD5(const char* input
)
1165 #if defined(CMAKE_BUILD_WITH_CMAKE)
1167 cmsysMD5
* md5
= cmsysMD5_New();
1168 cmsysMD5_Initialize(md5
);
1169 cmsysMD5_Append(md5
, reinterpret_cast<unsigned char const*>(input
), -1);
1170 cmsysMD5_FinalizeHex(md5
, md5out
);
1171 cmsysMD5_Delete(md5
);
1172 return std::string(md5out
, 32);
1175 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1180 void cmSystemTools::Glob(const char *directory
, const char *regexp
,
1181 std::vector
<std::string
>& files
)
1184 cmsys::RegularExpression
reg(regexp
);
1186 if (d
.Load(directory
))
1190 numf
= d
.GetNumberOfFiles();
1191 for (i
= 0; i
< numf
; i
++)
1193 std::string fname
= d
.GetFile(i
);
1194 if (reg
.find(fname
))
1196 files
.push_back(fname
);
1203 void cmSystemTools::GlobDirs(const char *fullPath
,
1204 std::vector
<std::string
>& files
)
1206 std::string path
= fullPath
;
1207 std::string::size_type pos
= path
.find("/*");
1208 if(pos
== std::string::npos
)
1210 files
.push_back(fullPath
);
1213 std::string startPath
= path
.substr(0, pos
);
1214 std::string finishPath
= path
.substr(pos
+2);
1217 if (d
.Load(startPath
.c_str()))
1219 for (unsigned int i
= 0; i
< d
.GetNumberOfFiles(); ++i
)
1221 if((std::string(d
.GetFile(i
)) != ".")
1222 && (std::string(d
.GetFile(i
)) != ".."))
1224 std::string fname
= startPath
;
1226 fname
+= d
.GetFile(i
);
1227 if(cmSystemTools::FileIsDirectory(fname
.c_str()))
1229 fname
+= finishPath
;
1230 cmSystemTools::GlobDirs(fname
.c_str(), files
);
1238 void cmSystemTools::ExpandList(std::vector
<std::string
> const& arguments
,
1239 std::vector
<std::string
>& newargs
)
1241 std::vector
<std::string
>::const_iterator i
;
1242 for(i
= arguments
.begin();i
!= arguments
.end(); ++i
)
1244 cmSystemTools::ExpandListArgument(*i
, newargs
);
1248 void cmSystemTools::ExpandListArgument(const std::string
& arg
,
1249 std::vector
<std::string
>& newargs
,
1252 // If argument is empty, it is an empty list.
1253 if(arg
.length() == 0 && !emptyArgs
)
1257 // if there are no ; in the name then just copy the current string
1258 if(arg
.find(';') == std::string::npos
)
1260 newargs
.push_back(arg
);
1263 std::vector
<char> newArgVec
;
1264 // Break the string at non-escaped semicolons not nested in [].
1265 int squareNesting
= 0;
1266 for(const char* c
= arg
.c_str(); *c
; ++c
)
1272 // We only want to allow escaping of semicolons. Other
1273 // escapes should not be processed here.
1277 newArgVec
.push_back(*c
);
1281 newArgVec
.push_back('\\');
1284 newArgVec
.push_back(*c
);
1288 // Terminate the loop properly.
1296 newArgVec
.push_back(*c
);
1301 newArgVec
.push_back(*c
);
1305 // Break the string here if we are not nested inside square
1307 if(squareNesting
== 0)
1309 if ( newArgVec
.size() || emptyArgs
)
1311 // Add the last argument if the string is not empty.
1312 newArgVec
.push_back(0);
1313 newargs
.push_back(&*newArgVec
.begin());
1319 newArgVec
.push_back(*c
);
1324 // Just append this character.
1325 newArgVec
.push_back(*c
);
1329 if ( newArgVec
.size() || emptyArgs
)
1331 // Add the last argument if the string is not empty.
1332 newArgVec
.push_back(0);
1333 newargs
.push_back(&*newArgVec
.begin());
1337 bool cmSystemTools::SimpleGlob(const cmStdString
& glob
,
1338 std::vector
<cmStdString
>& files
,
1342 if ( glob
[glob
.size()-1] != '*' )
1346 std::string path
= cmSystemTools::GetFilenamePath(glob
);
1347 std::string ppath
= cmSystemTools::GetFilenameName(glob
);
1348 ppath
= ppath
.substr(0, ppath
.size()-1);
1349 if ( path
.size() == 0 )
1356 if (d
.Load(path
.c_str()))
1358 for (unsigned int i
= 0; i
< d
.GetNumberOfFiles(); ++i
)
1360 if((std::string(d
.GetFile(i
)) != ".")
1361 && (std::string(d
.GetFile(i
)) != ".."))
1363 std::string fname
= path
;
1364 if ( path
[path
.size()-1] != '/' )
1368 fname
+= d
.GetFile(i
);
1369 std::string sfname
= d
.GetFile(i
);
1370 if ( type
> 0 && cmSystemTools::FileIsDirectory(fname
.c_str()) )
1374 if ( type
< 0 && !cmSystemTools::FileIsDirectory(fname
.c_str()) )
1378 if ( sfname
.size() >= ppath
.size() &&
1379 sfname
.substr(0, ppath
.size()) ==
1382 files
.push_back(fname
);
1391 cmSystemTools::FileFormat
cmSystemTools::GetFileFormat(const char* cext
)
1393 if ( ! cext
|| *cext
== 0 )
1395 return cmSystemTools::NO_FILE_FORMAT
;
1397 //std::string ext = cmSystemTools::LowerCase(cext);
1398 std::string ext
= cext
;
1399 if ( ext
== "c" || ext
== ".c" ||
1400 ext
== "m" || ext
== ".m"
1401 ) { return cmSystemTools::C_FILE_FORMAT
; }
1403 ext
== "C" || ext
== ".C" ||
1404 ext
== "M" || ext
== ".M" ||
1405 ext
== "c++" || ext
== ".c++" ||
1406 ext
== "cc" || ext
== ".cc" ||
1407 ext
== "cpp" || ext
== ".cpp" ||
1408 ext
== "cxx" || ext
== ".cxx" ||
1409 ext
== "mm" || ext
== ".mm"
1410 ) { return cmSystemTools::CXX_FILE_FORMAT
; }
1412 ext
== "f" || ext
== ".f" ||
1413 ext
== "F" || ext
== ".F" ||
1414 ext
== "f77" || ext
== ".f77" ||
1415 ext
== "f90" || ext
== ".f90" ||
1416 ext
== "for" || ext
== ".for" ||
1417 ext
== "f95" || ext
== ".f95"
1418 ) { return cmSystemTools::FORTRAN_FILE_FORMAT
; }
1419 if ( ext
== "java" || ext
== ".java" )
1420 { return cmSystemTools::JAVA_FILE_FORMAT
; }
1422 ext
== "H" || ext
== ".H" ||
1423 ext
== "h" || ext
== ".h" ||
1424 ext
== "h++" || ext
== ".h++" ||
1425 ext
== "hm" || ext
== ".hm" ||
1426 ext
== "hpp" || ext
== ".hpp" ||
1427 ext
== "hxx" || ext
== ".hxx" ||
1428 ext
== "in" || ext
== ".in" ||
1429 ext
== "txx" || ext
== ".txx"
1430 ) { return cmSystemTools::HEADER_FILE_FORMAT
; }
1431 if ( ext
== "rc" || ext
== ".rc" )
1432 { return cmSystemTools::RESOURCE_FILE_FORMAT
; }
1433 if ( ext
== "def" || ext
== ".def" )
1434 { return cmSystemTools::DEFINITION_FILE_FORMAT
; }
1435 if ( ext
== "lib" || ext
== ".lib" ||
1436 ext
== "a" || ext
== ".a")
1437 { return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT
; }
1438 if ( ext
== "o" || ext
== ".o" ||
1439 ext
== "obj" || ext
== ".obj")
1440 { return cmSystemTools::OBJECT_FILE_FORMAT
; }
1442 if ( ext
== "dylib" || ext
== ".dylib" )
1443 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT
; }
1444 if ( ext
== "so" || ext
== ".so" ||
1445 ext
== "bundle" || ext
== ".bundle" )
1446 { return cmSystemTools::MODULE_FILE_FORMAT
; }
1448 if ( ext
== "so" || ext
== ".so" ||
1449 ext
== "sl" || ext
== ".sl" ||
1450 ext
== "dll" || ext
== ".dll" )
1451 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT
; }
1453 return cmSystemTools::UNKNOWN_FILE_FORMAT
;
1456 bool cmSystemTools::Split(const char* s
, std::vector
<cmStdString
>& l
)
1458 std::vector
<std::string
> temp
;
1459 bool res
= Superclass::Split(s
, temp
);
1460 for(std::vector
<std::string
>::const_iterator i
= temp
.begin();
1461 i
!= temp
.end(); ++i
)
1468 std::string
cmSystemTools::ConvertToOutputPath(const char* path
)
1470 #if defined(_WIN32) && !defined(__CYGWIN__)
1471 if(s_ForceUnixPaths
)
1473 return cmSystemTools::ConvertToUnixOutputPath(path
);
1475 return cmSystemTools::ConvertToWindowsOutputPath(path
);
1477 return cmSystemTools::ConvertToUnixOutputPath(path
);
1481 void cmSystemTools::ConvertToOutputSlashes(std::string
& path
)
1483 #if defined(_WIN32) && !defined(__CYGWIN__)
1484 if(!s_ForceUnixPaths
)
1486 // Convert to windows slashes.
1487 std::string::size_type pos
= 0;
1488 while((pos
= path
.find('/', pos
)) != std::string::npos
)
1494 static_cast<void>(path
);
1498 std::string
cmSystemTools::ConvertToRunCommandPath(const char* path
)
1500 #if defined(_WIN32) && !defined(__CYGWIN__)
1501 return cmSystemTools::ConvertToWindowsOutputPath(path
);
1503 return cmSystemTools::ConvertToUnixOutputPath(path
);
1507 bool cmSystemTools::StringEndsWith(const char* str1
, const char* str2
)
1509 if ( !str1
|| !str2
|| strlen(str1
) < strlen(str2
) )
1513 return !strncmp(str1
+ (strlen(str1
)-strlen(str2
)), str2
, strlen(str2
));
1516 // compute the relative path from here to there
1517 std::string
cmSystemTools::RelativePath(const char* local
, const char* remote
)
1519 if(!cmSystemTools::FileIsFullPath(local
))
1521 cmSystemTools::Error("RelativePath must be passed a full path to local: ",
1524 if(!cmSystemTools::FileIsFullPath(remote
))
1526 cmSystemTools::Error
1527 ("RelativePath must be passed a full path to remote: ", remote
);
1529 return cmsys::SystemTools::RelativePath(local
, remote
);
1532 class cmDeletingCharVector
: public std::vector
<char*>
1535 ~cmDeletingCharVector()
1537 for(std::vector
<char*>::iterator i
= this->begin();
1538 i
!= this->end(); ++i
)
1546 bool cmSystemTools::PutEnv(const char* value
)
1548 static cmDeletingCharVector localEnvironment
;
1549 char* envVar
= new char[strlen(value
)+1];
1550 strcpy(envVar
, value
);
1551 int ret
= putenv(envVar
);
1552 // save the pointer in the static vector so that it can
1553 // be deleted on exit
1554 localEnvironment
.push_back(envVar
);
1558 #ifdef CMAKE_BUILD_WITH_CMAKE
1559 //----------------------------------------------------------------------
1560 bool cmSystemTools::UnsetEnv(const char* value
)
1562 #if !defined(HAVE_UNSETENV)
1563 std::string var
= value
;
1565 return cmSystemTools::PutEnv(var
.c_str());
1572 //----------------------------------------------------------------------
1573 std::vector
<std::string
> cmSystemTools::GetEnvironmentVariables()
1575 std::vector
<std::string
> env
;
1577 for ( cc
= 0; environ
[cc
]; ++ cc
)
1579 env
.push_back(environ
[cc
]);
1584 //----------------------------------------------------------------------
1585 std::vector
<std::string
> cmSystemTools::AppendEnv(
1586 std::vector
<std::string
>* env
)
1588 std::vector
<std::string
> origEnv
= GetEnvironmentVariables();
1590 if (env
&& env
->size()>0)
1592 std::vector
<std::string
>::const_iterator eit
;
1594 for (eit
= env
->begin(); eit
!= env
->end(); ++eit
)
1596 PutEnv(eit
->c_str());
1603 //----------------------------------------------------------------------
1604 void cmSystemTools::RestoreEnv(const std::vector
<std::string
>& env
)
1606 std::vector
<std::string
>::const_iterator eit
;
1608 // First clear everything in the current environment:
1610 std::vector
<std::string
> currentEnv
= GetEnvironmentVariables();
1611 for (eit
= currentEnv
.begin(); eit
!= currentEnv
.end(); ++eit
)
1613 std::string
var(*eit
);
1615 std::string::size_type pos
= var
.find("=");
1616 if (pos
!= std::string::npos
)
1618 var
= var
.substr(0, pos
);
1621 UnsetEnv(var
.c_str());
1624 // Then put back each entry from the original environment:
1626 for (eit
= env
.begin(); eit
!= env
.end(); ++eit
)
1628 PutEnv(eit
->c_str());
1633 void cmSystemTools::EnableVSConsoleOutput()
1635 // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
1636 // display output to the console unless this environment variable is
1637 // set. We need it to capture the output of these build tools.
1638 // Note for future work that one could pass "/out \\.\pipe\NAME" to
1639 // either of these executables where NAME is created with
1640 // CreateNamedPipe. This would bypass the internal buffering of the
1641 // output and allow it to be captured on the fly.
1643 cmSystemTools::PutEnv("vsconsoleoutput=1");
1647 bool cmSystemTools::IsPathToFramework(const char* path
)
1649 if(cmSystemTools::FileIsFullPath(path
))
1651 std::string libname
= path
;
1652 if(libname
.find(".framework") == libname
.size()+1-sizeof(".framework"))
1660 #if defined(CMAKE_BUILD_WITH_CMAKE)
1661 struct cmSystemToolsGZStruct
1667 int cmSystemToolsGZStructOpen(void* call_data
, const char *pathname
,
1668 int oflags
, mode_t mode
);
1669 int cmSystemToolsGZStructClose(void* call_data
);
1670 ssize_t
cmSystemToolsGZStructRead(void* call_data
, void* buf
, size_t count
);
1671 ssize_t
cmSystemToolsGZStructWrite(void* call_data
, const void* buf
,
1675 int cmSystemToolsGZStructOpen(void* call_data
, const char *pathname
,
1676 int oflags
, mode_t mode
)
1678 const char *gzoflags
;
1681 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1683 switch (oflags
& O_ACCMODE
)
1697 fd
= open(pathname
, oflags
, mode
);
1703 // no fchmod on BeOS 5...do pathname instead.
1704 #if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
1705 if ((oflags
& O_CREAT
) && chmod(pathname
, mode
))
1709 #elif !defined(_WIN32) || defined(__CYGWIN__)
1710 if ((oflags
& O_CREAT
) && fchmod(fd
, mode
))
1716 gzf
->GZFile
= gzdopen(fd
, gzoflags
);
1726 int cmSystemToolsGZStructClose(void* call_data
)
1728 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1729 return gzclose(gzf
->GZFile
);
1732 ssize_t
cmSystemToolsGZStructRead(void* call_data
, void* buf
, size_t count
)
1734 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1735 return gzread(gzf
->GZFile
, buf
, static_cast<int>(count
));
1738 ssize_t
cmSystemToolsGZStructWrite(void* call_data
, const void* buf
,
1741 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1742 return gzwrite(gzf
->GZFile
, (void*)buf
, static_cast<int>(count
));
1747 bool cmSystemTools::CreateTar(const char* outFileName
,
1748 const std::vector
<cmStdString
>& files
,
1749 bool gzip
, bool verbose
)
1751 #if defined(CMAKE_BUILD_WITH_CMAKE)
1753 char buf
[TAR_MAXPATHLEN
];
1754 char pathname
[TAR_MAXPATHLEN
];
1755 cmSystemToolsGZStruct gzs
;
1757 tartype_t gztype
= {
1758 (openfunc_t
)cmSystemToolsGZStructOpen
,
1759 (closefunc_t
)cmSystemToolsGZStructClose
,
1760 (readfunc_t
)cmSystemToolsGZStructRead
,
1761 (writefunc_t
)cmSystemToolsGZStructWrite
,
1765 // Ok, this libtar is not const safe. for now use auto_ptr hack
1766 char* realName
= new char[ strlen(outFileName
) + 1 ];
1767 std::auto_ptr
<char> realNamePtr(realName
);
1768 strcpy(realName
, outFileName
);
1772 options
|= TAR_VERBOSE
;
1777 if (tar_open(&t
, realName
,
1778 (gzip
? &gztype
: NULL
),
1779 O_WRONLY
| O_CREAT
, 0644,
1782 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno
));
1786 std::vector
<cmStdString
>::const_iterator it
;
1787 for (it
= files
.begin(); it
!= files
.end(); ++ it
)
1789 strncpy(pathname
, it
->c_str(), sizeof(pathname
));
1790 pathname
[sizeof(pathname
)-1] = 0;
1791 strncpy(buf
, pathname
, sizeof(buf
));
1792 buf
[sizeof(buf
)-1] = 0;
1793 if (tar_append_tree(t
, buf
, pathname
) != 0)
1795 cmOStringStream ostr
;
1796 ostr
<< "Problem with tar_append_tree(\"" << buf
<< "\", \""
1797 << pathname
<< "\"): "
1799 cmSystemTools::Error(ostr
.str().c_str());
1805 if (tar_append_eof(t
) != 0)
1807 cmSystemTools::Error("Problem with tar_append_eof(): ", strerror(errno
));
1812 if (tar_close(t
) != 0)
1814 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno
));
1827 bool cmSystemTools::ExtractTar(const char* outFileName
,
1828 const std::vector
<cmStdString
>& files
,
1829 bool gzip
, bool verbose
)
1832 #if defined(CMAKE_BUILD_WITH_CMAKE)
1834 cmSystemToolsGZStruct gzs
;
1836 tartype_t gztype
= {
1837 cmSystemToolsGZStructOpen
,
1838 cmSystemToolsGZStructClose
,
1839 cmSystemToolsGZStructRead
,
1840 cmSystemToolsGZStructWrite
,
1844 // Ok, this libtar is not const safe. for now use auto_ptr hack
1845 char* realName
= new char[ strlen(outFileName
) + 1 ];
1846 std::auto_ptr
<char> realNamePtr(realName
);
1847 strcpy(realName
, outFileName
);
1848 if (tar_open(&t
, realName
,
1849 (gzip
? &gztype
: NULL
),
1855 (verbose
?TAR_VERBOSE
:0)
1858 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno
));
1862 if (tar_extract_all(t
, 0) != 0)
1864 cmSystemTools::Error("Problem with tar_extract_all(): ", strerror(errno
));
1868 if (tar_close(t
) != 0)
1870 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno
));
1882 bool cmSystemTools::ListTar(const char* outFileName
,
1883 std::vector
<cmStdString
>& files
, bool gzip
,
1886 #if defined(CMAKE_BUILD_WITH_CMAKE)
1888 cmSystemToolsGZStruct gzs
;
1890 tartype_t gztype
= {
1891 cmSystemToolsGZStructOpen
,
1892 cmSystemToolsGZStructClose
,
1893 cmSystemToolsGZStructRead
,
1894 cmSystemToolsGZStructWrite
,
1898 // Ok, this libtar is not const safe. for now use auto_ptr hack
1899 char* realName
= new char[ strlen(outFileName
) + 1 ];
1900 std::auto_ptr
<char> realNamePtr(realName
);
1901 strcpy(realName
, outFileName
);
1902 if (tar_open(&t
, realName
,
1903 (gzip
? &gztype
: NULL
),
1909 (verbose
?TAR_VERBOSE
:0)
1912 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno
));
1916 while ((th_read(t
)) == 0)
1918 const char* filename
= th_get_pathname(t
);
1919 files
.push_back(filename
);
1923 th_print_long_ls(t
);
1927 std::cout
<< filename
<< std::endl
;
1933 if (TH_ISREG(t
) && tar_skip_regfile(t
) != 0)
1935 cmSystemTools::Error("Problem with tar_skip_regfile(): ",
1941 if (tar_close(t
) != 0)
1943 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno
));
1956 int cmSystemTools::WaitForLine(cmsysProcess
* process
, std::string
& line
,
1958 std::vector
<char>& out
,
1959 std::vector
<char>& err
)
1962 std::vector
<char>::iterator outiter
= out
.begin();
1963 std::vector
<char>::iterator erriter
= err
.begin();
1966 // Check for a newline in stdout.
1967 for(;outiter
!= out
.end(); ++outiter
)
1969 if((*outiter
== '\r') && ((outiter
+1) == out
.end()))
1973 else if(*outiter
== '\n' || *outiter
== '\0')
1975 int length
= outiter
-out
.begin();
1976 if(length
> 1 && *(outiter
-1) == '\r')
1982 line
.append(&out
[0], length
);
1984 out
.erase(out
.begin(), outiter
+1);
1985 return cmsysProcess_Pipe_STDOUT
;
1989 // Check for a newline in stderr.
1990 for(;erriter
!= err
.end(); ++erriter
)
1992 if((*erriter
== '\r') && ((erriter
+1) == err
.end()))
1996 else if(*erriter
== '\n' || *erriter
== '\0')
1998 int length
= erriter
-err
.begin();
1999 if(length
> 1 && *(erriter
-1) == '\r')
2005 line
.append(&err
[0], length
);
2007 err
.erase(err
.begin(), erriter
+1);
2008 return cmsysProcess_Pipe_STDERR
;
2012 // No newlines found. Wait for more data from the process.
2015 int pipe
= cmsysProcess_WaitForData(process
, &data
, &length
, &timeout
);
2016 if(pipe
== cmsysProcess_Pipe_Timeout
)
2018 // Timeout has been exceeded.
2021 else if(pipe
== cmsysProcess_Pipe_STDOUT
)
2023 // Append to the stdout buffer.
2024 std::vector
<char>::size_type size
= out
.size();
2025 out
.insert(out
.end(), data
, data
+length
);
2026 outiter
= out
.begin()+size
;
2028 else if(pipe
== cmsysProcess_Pipe_STDERR
)
2030 // Append to the stderr buffer.
2031 std::vector
<char>::size_type size
= err
.size();
2032 err
.insert(err
.end(), data
, data
+length
);
2033 erriter
= err
.begin()+size
;
2035 else if(pipe
== cmsysProcess_Pipe_None
)
2037 // Both stdout and stderr pipes have broken. Return leftover data.
2040 line
.append(&out
[0], outiter
-out
.begin());
2041 out
.erase(out
.begin(), out
.end());
2042 return cmsysProcess_Pipe_STDOUT
;
2044 else if(!err
.empty())
2046 line
.append(&err
[0], erriter
-err
.begin());
2047 err
.erase(err
.begin(), err
.end());
2048 return cmsysProcess_Pipe_STDERR
;
2052 return cmsysProcess_Pipe_None
;
2058 void cmSystemTools::DoNotInheritStdPipes()
2061 // Check to see if we are attached to a console
2062 // if so, then do not stop the inherited pipes
2063 // or stdout and stderr will not show up in dos
2065 CONSOLE_SCREEN_BUFFER_INFO hOutInfo
;
2066 HANDLE hOut
= GetStdHandle(STD_OUTPUT_HANDLE
);
2067 if(GetConsoleScreenBufferInfo(hOut
, &hOutInfo
))
2072 HANDLE out
= GetStdHandle(STD_OUTPUT_HANDLE
);
2073 DuplicateHandle(GetCurrentProcess(), out
,
2074 GetCurrentProcess(), &out
, 0, FALSE
,
2075 DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE
);
2076 SetStdHandle(STD_OUTPUT_HANDLE
, out
);
2079 HANDLE out
= GetStdHandle(STD_ERROR_HANDLE
);
2080 DuplicateHandle(GetCurrentProcess(), out
,
2081 GetCurrentProcess(), &out
, 0, FALSE
,
2082 DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE
);
2083 SetStdHandle(STD_ERROR_HANDLE
, out
);
2088 //----------------------------------------------------------------------------
2089 bool cmSystemTools::CopyFileTime(const char* fromFile
, const char* toFile
)
2091 #if defined(_WIN32) && !defined(__CYGWIN__)
2092 cmSystemToolsWindowsHandle hFrom
=
2093 CreateFile(fromFile
, GENERIC_READ
, FILE_SHARE_READ
, 0,
2094 OPEN_EXISTING
, 0, 0);
2095 cmSystemToolsWindowsHandle hTo
=
2096 CreateFile(toFile
, GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
2101 FILETIME timeCreation
;
2102 FILETIME timeLastAccess
;
2103 FILETIME timeLastWrite
;
2104 if(!GetFileTime(hFrom
, &timeCreation
, &timeLastAccess
, &timeLastWrite
))
2108 if(!SetFileTime(hTo
, &timeCreation
, &timeLastAccess
, &timeLastWrite
))
2113 struct stat fromStat
;
2114 if(stat(fromFile
, &fromStat
) < 0)
2120 buf
.actime
= fromStat
.st_atime
;
2121 buf
.modtime
= fromStat
.st_mtime
;
2122 if(utime(toFile
, &buf
) < 0)
2130 //----------------------------------------------------------------------------
2131 cmSystemToolsFileTime
* cmSystemTools::FileTimeNew()
2133 return new cmSystemToolsFileTime
;
2136 //----------------------------------------------------------------------------
2137 void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime
* t
)
2142 //----------------------------------------------------------------------------
2143 bool cmSystemTools::FileTimeGet(const char* fname
, cmSystemToolsFileTime
* t
)
2145 #if defined(_WIN32) && !defined(__CYGWIN__)
2146 cmSystemToolsWindowsHandle h
=
2147 CreateFile(fname
, GENERIC_READ
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
2152 if(!GetFileTime(h
, &t
->timeCreation
, &t
->timeLastAccess
, &t
->timeLastWrite
))
2158 if(stat(fname
, &st
) < 0)
2162 t
->timeBuf
.actime
= st
.st_atime
;
2163 t
->timeBuf
.modtime
= st
.st_mtime
;
2168 //----------------------------------------------------------------------------
2169 bool cmSystemTools::FileTimeSet(const char* fname
, cmSystemToolsFileTime
* t
)
2171 #if defined(_WIN32) && !defined(__CYGWIN__)
2172 cmSystemToolsWindowsHandle h
=
2173 CreateFile(fname
, GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
2178 if(!SetFileTime(h
, &t
->timeCreation
, &t
->timeLastAccess
, &t
->timeLastWrite
))
2183 if(utime(fname
, &t
->timeBuf
) < 0)
2191 //----------------------------------------------------------------------------
2192 static std::string cmSystemToolsExecutableDirectory
;
2193 void cmSystemTools::FindExecutableDirectory(const char* argv0
)
2195 #if defined(_WIN32) && !defined(__CYGWIN__)
2196 (void)argv0
; // ignore this on windows
2197 char modulepath
[_MAX_PATH
];
2198 ::GetModuleFileName(NULL
, modulepath
, sizeof(modulepath
));
2199 cmSystemToolsExecutableDirectory
=
2200 cmSystemTools::GetFilenamePath(modulepath
);
2203 std::string errorMsg
;
2205 if(cmSystemTools::FindProgramPath(argv0
, exe
, errorMsg
))
2208 exe
= cmSystemTools::GetRealPath(exe
.c_str());
2209 cmSystemToolsExecutableDirectory
=
2210 cmSystemTools::GetFilenamePath(exe
.c_str());
2219 //----------------------------------------------------------------------------
2220 const char* cmSystemTools::GetExecutableDirectory()
2222 return cmSystemToolsExecutableDirectory
.c_str();
2225 //----------------------------------------------------------------------------
2226 #if defined(CMAKE_BUILD_WITH_CMAKE)
2227 void cmSystemTools::MakefileColorEcho(int color
, const char* message
,
2228 bool newline
, bool enabled
)
2230 // On some platforms (an MSYS prompt) cmsysTerminal may not be able
2231 // to determine whether the stream is displayed on a tty. In this
2232 // case it assumes no unless we tell it otherwise. Since we want
2233 // color messages to be displayed for users we will assume yes.
2234 // However, we can test for some situations when the answer is most
2236 int assumeTTY
= cmsysTerminal_Color_AssumeTTY
;
2237 if(cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
2238 cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
2239 cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE"))
2241 // Avoid printing color escapes during dashboard builds.
2247 cmsysTerminal_cfprintf(color
| assumeTTY
, stdout
, "%s%s",
2248 message
, newline
? "\n" : "");
2252 // Color is disabled. Print without color.
2253 fprintf(stdout
, "%s%s", message
, newline
? "\n" : "");
2258 //----------------------------------------------------------------------------
2259 bool cmSystemTools::GuessLibrarySOName(std::string
const& fullPath
,
2260 std::string
& soname
)
2262 // For ELF shared libraries use a real parser to get the correct
2264 #if defined(CMAKE_USE_ELF_PARSER)
2265 cmELF
elf(fullPath
.c_str());
2268 return elf
.GetSOName(soname
);
2272 // If the file is not a symlink we have no guess for its soname.
2273 if(!cmSystemTools::FileIsSymlink(fullPath
.c_str()))
2277 if(!cmSystemTools::ReadSymlink(fullPath
.c_str(), soname
))
2282 // If the symlink has a path component we have no guess for the soname.
2283 if(!cmSystemTools::GetFilenamePath(soname
).empty())
2288 // If the symlink points at an extended version of the same name
2289 // assume it is the soname.
2290 std::string name
= cmSystemTools::GetFilenameName(fullPath
);
2291 if(soname
.length() > name
.length() &&
2292 soname
.substr(0, name
.length()) == name
)
2299 //----------------------------------------------------------------------------
2300 #if defined(CMAKE_USE_ELF_PARSER)
2301 std::string::size_type
cmSystemToolsFindRPath(std::string
const& have
,
2302 std::string
const& want
)
2304 // Search for the desired rpath.
2305 std::string::size_type pos
= have
.find(want
);
2307 // If the path is not present we are done.
2308 if(pos
== std::string::npos
)
2313 // Build a regex to match a properly separated path instance.
2314 std::string regex_str
= "(^|:)(";
2315 for(std::string::const_iterator i
= want
.begin(); i
!= want
.end(); ++i
)
2318 if(!(('a' <= ch
&& ch
<= 'z') ||
2319 ('A' <= ch
&& ch
<= 'Z') ||
2320 ('0' <= ch
&& ch
<= '9')))
2322 // Escape the non-alphanumeric character.
2325 // Store the character.
2326 regex_str
.append(1, static_cast<char>(ch
));
2328 regex_str
+= ")(:|$)";
2330 // Look for the separated path.
2331 cmsys::RegularExpression
regex(regex_str
.c_str());
2332 if(regex
.find(have
))
2334 // Return the position of the path portion.
2335 return regex
.start(2);
2339 // The desired rpath was not found.
2340 return std::string::npos
;
2345 #if defined(CMAKE_USE_ELF_PARSER)
2346 struct cmSystemToolsRPathInfo
2348 unsigned long Position
;
2355 //----------------------------------------------------------------------------
2356 bool cmSystemTools::ChangeRPath(std::string
const& file
,
2357 std::string
const& oldRPath
,
2358 std::string
const& newRPath
,
2362 #if defined(CMAKE_USE_ELF_PARSER)
2368 cmSystemToolsRPathInfo rp
[2];
2370 // Parse the ELF binary.
2371 cmELF
elf(file
.c_str());
2373 // Get the RPATH and RUNPATH entries from it.
2375 cmELF::StringEntry
const* se
[2] = {0, 0};
2376 const char* se_name
[2] = {0, 0};
2377 if(cmELF::StringEntry
const* se_rpath
= elf
.GetRPath())
2379 se
[se_count
] = se_rpath
;
2380 se_name
[se_count
] = "RPATH";
2383 if(cmELF::StringEntry
const* se_runpath
= elf
.GetRunPath())
2385 se
[se_count
] = se_runpath
;
2386 se_name
[se_count
] = "RUNPATH";
2391 if(newRPath
.empty())
2393 // The new rpath is empty and there is no rpath anyway so it is
2401 *emsg
= "No valid ELF RPATH or RUNPATH entry exists in the file; ";
2402 *emsg
+= elf
.GetErrorMessage();
2408 for(int i
=0; i
< se_count
; ++i
)
2410 // If both RPATH and RUNPATH refer to the same string literal it
2411 // needs to be changed only once.
2412 if(rp_count
&& rp
[0].Position
== se
[i
]->Position
)
2417 // Make sure the current rpath contains the old rpath.
2418 std::string::size_type pos
=
2419 cmSystemToolsFindRPath(se
[i
]->Value
, oldRPath
);
2420 if(pos
== std::string::npos
)
2422 // If it contains the new rpath instead then it is okay.
2423 if(cmSystemToolsFindRPath(se
[i
]->Value
, newRPath
) != std::string::npos
)
2430 e
<< "The current " << se_name
[i
] << " is:\n"
2431 << " " << se
[i
]->Value
<< "\n"
2432 << "which does not contain:\n"
2433 << " " << oldRPath
<< "\n"
2434 << "as was expected.";
2440 // Store information about the entry in the file.
2441 rp
[rp_count
].Position
= se
[i
]->Position
;
2442 rp
[rp_count
].Size
= se
[i
]->Size
;
2443 rp
[rp_count
].Name
= se_name
[i
];
2445 // Construct the new value which preserves the part of the path
2446 // not being changed.
2447 rp
[rp_count
].Value
= se
[i
]->Value
.substr(0, pos
);
2448 rp
[rp_count
].Value
+= newRPath
;
2449 rp
[rp_count
].Value
+= se
[i
]->Value
.substr(pos
+oldRPath
.length(),
2452 // Make sure there is enough room to store the new rpath and at
2453 // least one null terminator.
2454 if(rp
[rp_count
].Size
< rp
[rp_count
].Value
.length()+1)
2458 *emsg
= "The replacement path is too long for the ";
2459 *emsg
+= se_name
[i
];
2465 // This entry is ready for update.
2470 // If no runtime path needs to be changed, we are done.
2477 // Open the file for update.
2478 std::ofstream
f(file
.c_str(),
2479 std::ios::in
| std::ios::out
| std::ios::binary
);
2484 *emsg
= "Error opening file for update.";
2489 // Store the new RPATH and RUNPATH strings.
2490 for(int i
=0; i
< rp_count
; ++i
)
2492 // Seek to the RPATH position.
2493 if(!f
.seekp(rp
[i
].Position
))
2497 *emsg
= "Error seeking to ";
2498 *emsg
+= rp
[i
].Name
;
2499 *emsg
+= " position.";
2504 // Write the new rpath. Follow it with enough null terminators to
2505 // fill the string table entry.
2507 for(unsigned long j
=rp
[i
].Value
.length(); j
< rp
[i
].Size
; ++j
)
2512 // Make sure it wrote correctly.
2517 *emsg
= "Error writing the new ";
2518 *emsg
+= rp
[i
].Name
;
2519 *emsg
+= " string to the file.";
2526 // Everything was updated successfully.
2542 //----------------------------------------------------------------------------
2543 bool cmSystemTools::RemoveRPath(std::string
const& file
, std::string
* emsg
,
2546 #if defined(CMAKE_USE_ELF_PARSER)
2552 unsigned long zeroPosition
[2] = {0,0};
2553 unsigned long zeroSize
[2] = {0,0};
2554 unsigned long bytesBegin
= 0;
2555 std::vector
<char> bytes
;
2557 // Parse the ELF binary.
2558 cmELF
elf(file
.c_str());
2560 // Get the RPATH and RUNPATH entries from it and sort them by index
2561 // in the dynamic section header.
2563 cmELF::StringEntry
const* se
[2] = {0, 0};
2564 if(cmELF::StringEntry
const* se_rpath
= elf
.GetRPath())
2566 se
[se_count
++] = se_rpath
;
2568 if(cmELF::StringEntry
const* se_runpath
= elf
.GetRunPath())
2570 se
[se_count
++] = se_runpath
;
2574 // There is no RPATH or RUNPATH anyway.
2577 if(se_count
== 2 && se
[1]->IndexInSection
< se
[0]->IndexInSection
)
2579 cmsys_stl::swap(se
[0], se
[1]);
2582 // Get the size of the dynamic section header.
2583 unsigned int count
= elf
.GetDynamicEntryCount();
2586 // This should happen only for invalid ELF files where a DT_NULL
2587 // appears before the end of the table.
2590 *emsg
= "DYNAMIC section contains a DT_NULL before the end.";
2595 // Save information about the string entries to be zeroed.
2596 zeroCount
= se_count
;
2597 for(int i
=0; i
< se_count
; ++i
)
2599 zeroPosition
[i
] = se
[i
]->Position
;
2600 zeroSize
[i
] = se
[i
]->Size
;
2603 // Get the range of file positions corresponding to each entry and
2604 // the rest of the table after them.
2605 unsigned long entryBegin
[3] = {0,0,0};
2606 unsigned long entryEnd
[2] = {0,0};
2607 for(int i
=0; i
< se_count
; ++i
)
2609 entryBegin
[i
] = elf
.GetDynamicEntryPosition(se
[i
]->IndexInSection
);
2610 entryEnd
[i
] = elf
.GetDynamicEntryPosition(se
[i
]->IndexInSection
+1);
2612 entryBegin
[se_count
] = elf
.GetDynamicEntryPosition(count
);
2614 // The data are to be written over the old table entries starting at
2615 // the first one being removed.
2616 bytesBegin
= entryBegin
[0];
2617 unsigned long bytesEnd
= entryBegin
[se_count
];
2619 // Allocate a buffer to hold the part of the file to be written.
2620 // Initialize it with zeros.
2621 bytes
.resize(bytesEnd
- bytesBegin
, 0);
2623 // Read the part of the DYNAMIC section header that will move.
2624 // The remainder of the buffer will be left with zeros which
2625 // represent a DT_NULL entry.
2626 char* data
= &bytes
[0];
2627 for(int i
=0; i
< se_count
; ++i
)
2629 // Read data between the entries being removed.
2630 unsigned long sz
= entryBegin
[i
+1] - entryEnd
[i
];
2631 if(sz
> 0 && !elf
.ReadBytes(entryEnd
[i
], sz
, data
))
2635 *emsg
= "Failed to read DYNAMIC section header.";
2643 // Open the file for update.
2644 std::ofstream
f(file
.c_str(),
2645 std::ios::in
| std::ios::out
| std::ios::binary
);
2650 *emsg
= "Error opening file for update.";
2655 // Write the new DYNAMIC table header.
2656 if(!f
.seekp(bytesBegin
))
2660 *emsg
= "Error seeking to DYNAMIC table header for RPATH.";
2664 if(!f
.write(&bytes
[0], bytes
.size()))
2668 *emsg
= "Error replacing DYNAMIC table header.";
2673 // Fill the RPATH and RUNPATH strings with zero bytes.
2674 for(int i
=0; i
< zeroCount
; ++i
)
2676 if(!f
.seekp(zeroPosition
[i
]))
2680 *emsg
= "Error seeking to RPATH position.";
2684 for(unsigned long j
=0; j
< zeroSize
[i
]; ++j
)
2692 *emsg
= "Error writing the empty rpath string to the file.";
2698 // Everything was updated successfully.
2712 //----------------------------------------------------------------------------
2713 bool cmSystemTools::CheckRPath(std::string
const& file
,
2714 std::string
const& newRPath
)
2716 #if defined(CMAKE_USE_ELF_PARSER)
2717 // Parse the ELF binary.
2718 cmELF
elf(file
.c_str());
2720 // Get the RPATH or RUNPATH entry from it.
2721 cmELF::StringEntry
const* se
= elf
.GetRPath();
2724 se
= elf
.GetRunPath();
2727 // Make sure the current rpath contains the new rpath.
2728 if(newRPath
.empty())
2738 cmSystemToolsFindRPath(se
->Value
, newRPath
) != std::string::npos
)