1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmSystemTools.cxx,v $
6 Date: $Date: 2009-09-11 12:18:13 $
7 Version: $Revision: 1.401 $
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"
24 # include <malloc.h> /* for malloc/free on QNX */
27 #include <cmsys/RegularExpression.hxx>
28 #include <cmsys/Directory.hxx>
29 #include <cmsys/System.h>
30 #if defined(CMAKE_BUILD_WITH_CMAKE)
31 # include <cmsys/Terminal.h>
33 #include <cmsys/stl/algorithm>
38 # include <sys/types.h>
41 # include <sys/wait.h>
46 #if defined(_WIN32) && \
47 (defined(_MSC_VER) || defined(__WATCOMC__) || \
48 defined(__BORLANDC__) || defined(__MINGW32__))
52 #if defined(CMAKE_BUILD_WITH_CMAKE)
53 # include <libtar/libtar.h>
54 # include <memory> // auto_ptr
57 # include <cmsys/MD5.h>
60 #if defined(CMAKE_USE_ELF_PARSER)
64 class cmSystemToolsFileTime
67 #if defined(_WIN32) && !defined(__CYGWIN__)
68 FILETIME timeCreation
;
69 FILETIME timeLastAccess
;
70 FILETIME timeLastWrite
;
72 struct utimbuf timeBuf
;
76 #if defined(__sgi) && !defined(__GNUC__)
77 # pragma set woff 1375 /* base class destructor not virtual */
80 #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
81 // For GetEnvironmentVariables
83 extern __declspec( dllimport
) char** environ
;
85 extern char** environ
;
90 class cmSystemToolsWindowsHandle
93 cmSystemToolsWindowsHandle(HANDLE h
): handle_(h
) {}
94 ~cmSystemToolsWindowsHandle()
96 if(this->handle_
!= INVALID_HANDLE_VALUE
)
98 CloseHandle(this->handle_
);
101 operator bool() const { return this->handle_
!= INVALID_HANDLE_VALUE
; }
102 bool operator !() const { return this->handle_
== INVALID_HANDLE_VALUE
; }
103 operator HANDLE() const { return this->handle_
; }
109 bool cmSystemTools::s_RunCommandHideConsole
= false;
110 bool cmSystemTools::s_DisableRunCommandOutput
= false;
111 bool cmSystemTools::s_ErrorOccured
= false;
112 bool cmSystemTools::s_FatalErrorOccured
= false;
113 bool cmSystemTools::s_DisableMessages
= false;
114 bool cmSystemTools::s_ForceUnixPaths
= false;
116 std::string
cmSystemTools::s_Windows9xComspecSubstitute
= "command.com";
117 void cmSystemTools::SetWindows9xComspecSubstitute(const char* str
)
121 cmSystemTools::s_Windows9xComspecSubstitute
= str
;
124 const char* cmSystemTools::GetWindows9xComspecSubstitute()
126 return cmSystemTools::s_Windows9xComspecSubstitute
.c_str();
129 void (*cmSystemTools::s_ErrorCallback
)(const char*, const char*,
131 void (*cmSystemTools::s_StdoutCallback
)(const char*, int len
, void*);
132 void* cmSystemTools::s_ErrorCallbackClientData
= 0;
133 void* cmSystemTools::s_StdoutCallbackClientData
= 0;
135 // replace replace with with as many times as it shows up in source.
136 // write the result into source.
137 #if defined(_WIN32) && !defined(__CYGWIN__)
138 void cmSystemTools::ExpandRegistryValues(std::string
& source
, KeyWOW64 view
)
140 // Regular expression to match anything inside [...] that begins in HKEY.
141 // Note that there is a special rule for regular expressions to match a
142 // close square-bracket inside a list delimited by square brackets.
143 // The "[^]]" part of this expression will match any character except
144 // a close square-bracket. The ']' character must be the first in the
145 // list of characters inside the [^...] block of the expression.
146 cmsys::RegularExpression
regEntry("\\[(HKEY[^]]*)\\]");
148 // check for black line or comment
149 while (regEntry
.find(source
))
151 // the arguments are the second match
152 std::string key
= regEntry
.match(1);
154 if (ReadRegistryValue(key
.c_str(), val
, view
))
156 std::string reg
= "[";
158 cmSystemTools::ReplaceString(source
, reg
.c_str(), val
.c_str());
162 std::string reg
= "[";
164 cmSystemTools::ReplaceString(source
, reg
.c_str(), "/registry");
169 void cmSystemTools::ExpandRegistryValues(std::string
& source
, KeyWOW64
)
171 cmsys::RegularExpression
regEntry("\\[(HKEY[^]]*)\\]");
172 while (regEntry
.find(source
))
174 // the arguments are the second match
175 std::string key
= regEntry
.match(1);
177 std::string reg
= "[";
179 cmSystemTools::ReplaceString(source
, reg
.c_str(), "/registry");
185 std::string
cmSystemTools::EscapeQuotes(const char* str
)
187 std::string result
= "";
188 for(const char* ch
= str
; *ch
!= '\0'; ++ch
)
199 std::string
cmSystemTools::EscapeSpaces(const char* str
)
201 #if defined(_WIN32) && !defined(__CYGWIN__)
202 bool useDoubleQ
= true;
204 bool useDoubleQ
= false;
206 if(cmSystemTools::s_ForceUnixPaths
)
215 // if there are spaces
216 std::string temp
= str
;
217 if (temp
.find(" ") != std::string::npos
&&
218 temp
.find("\"")==std::string::npos
)
229 std::string result
= "";
230 for(const char* ch
= str
; *ch
!= '\0'; ++ch
)
242 void cmSystemTools::Error(const char* m1
, const char* m2
,
243 const char* m3
, const char* m4
)
245 std::string message
= "CMake Error: ";
262 cmSystemTools::s_ErrorOccured
= true;
263 cmSystemTools::Message(message
.c_str(),"Error");
267 void cmSystemTools::SetErrorCallback(ErrorCallback f
, void* clientData
)
270 s_ErrorCallbackClientData
= clientData
;
273 void cmSystemTools::SetStdoutCallback(StdoutCallback f
, void* clientData
)
275 s_StdoutCallback
= f
;
276 s_StdoutCallbackClientData
= clientData
;
279 void cmSystemTools::Stdout(const char* s
)
283 (*s_StdoutCallback
)(s
, static_cast<int>(strlen(s
)),
284 s_StdoutCallbackClientData
);
293 void cmSystemTools::Stdout(const char* s
, int length
)
297 (*s_StdoutCallback
)(s
, length
, s_StdoutCallbackClientData
);
301 std::cout
.write(s
, length
);
306 void cmSystemTools::Message(const char* m1
, const char *title
)
308 if(s_DisableMessages
)
314 (*s_ErrorCallback
)(m1
, title
, s_DisableMessages
,
315 s_ErrorCallbackClientData
);
320 std::cerr
<< m1
<< std::endl
<< std::flush
;
326 void cmSystemTools::ReportLastSystemError(const char* msg
)
329 m
+= ": System Error: ";
330 m
+= Superclass::GetLastSystemError();
331 cmSystemTools::Error(m
.c_str());
335 bool cmSystemTools::IsOn(const char* val
)
341 std::basic_string
<char> v
= val
;
343 for(std::basic_string
<char>::iterator c
= v
.begin();
348 return (v
== "ON" || v
== "1" || v
== "YES" || v
== "TRUE" || v
== "Y");
351 bool cmSystemTools::IsNOTFOUND(const char* val
)
353 size_t len
= strlen(val
);
354 const char* notfound
= "-NOTFOUND";
355 const size_t lenNotFound
= 9;
356 if(len
< lenNotFound
-1)
360 if(len
== lenNotFound
-1)
362 return ( strcmp(val
, "NOTFOUND") == 0);
364 return ((strncmp((val
+ (len
- lenNotFound
)), notfound
, lenNotFound
) == 0));
368 bool cmSystemTools::IsOff(const char* val
)
370 if (!val
|| strlen(val
) == 0)
374 std::basic_string
<char> v
= val
;
376 for(std::basic_string
<char>::iterator c
= v
.begin();
381 return (v
== "OFF" || v
== "0" || v
== "NO" || v
== "FALSE" ||
382 v
== "N" || cmSystemTools::IsNOTFOUND(v
.c_str()) || v
== "IGNORE");
385 //----------------------------------------------------------------------------
386 void cmSystemTools::ParseWindowsCommandLine(const char* command
,
387 std::vector
<std::string
>& args
)
389 // See the MSDN document "Parsing C Command-Line Arguments" at
390 // http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx for rules
391 // of parsing the windows command line.
393 bool in_argument
= false;
394 bool in_quotes
= false;
397 for(const char* c
= command
;*c
; ++c
)
406 int backslash_pairs
= backslashes
>> 1;
407 int backslash_escaped
= backslashes
& 1;
408 arg
.append(backslash_pairs
, '\\');
410 if(backslash_escaped
)
412 /* An odd number of backslashes precede this quote.
418 /* An even number of backslashes precede this quote.
419 It is not escaped. */
420 in_quotes
= !in_quotes
;
426 arg
.append(backslashes
, '\\');
448 arg
.append(backslashes
, '\\');
455 //----------------------------------------------------------------------------
456 class cmSystemToolsArgV
460 cmSystemToolsArgV(char** argv
): ArgV(argv
) {}
463 for(char** arg
= this->ArgV
; arg
&& *arg
; ++arg
)
469 void Store(std::vector
<std::string
>& args
) const
471 for(char** arg
= this->ArgV
; arg
&& *arg
; ++arg
)
473 args
.push_back(*arg
);
478 //----------------------------------------------------------------------------
479 void cmSystemTools::ParseUnixCommandLine(const char* command
,
480 std::vector
<std::string
>& args
)
482 // Invoke the underlying parser.
483 cmSystemToolsArgV argv
= cmsysSystem_Parse_CommandForUnix(command
, 0);
487 std::string
cmSystemTools::EscapeWindowsShellArgument(const char* arg
,
490 char local_buffer
[1024];
491 char* buffer
= local_buffer
;
492 int size
= cmsysSystem_Shell_GetArgumentSizeForWindows(arg
, shell_flags
);
495 buffer
= new char[size
];
497 cmsysSystem_Shell_GetArgumentForWindows(arg
, buffer
, shell_flags
);
498 std::string
result(buffer
);
499 if(buffer
!= local_buffer
)
506 std::vector
<cmStdString
> cmSystemTools::ParseArguments(const char* command
)
508 std::vector
<cmStdString
> args
;
511 bool win_path
= false;
513 if ((command
[0] != '/' && command
[1] == ':' && command
[2] == '\\') ||
514 (command
[0] == '\"' && command
[1] != '/' && command
[2] == ':'
515 && command
[3] == '\\') ||
516 (command
[0] == '\'' && command
[1] != '/' && command
[2] == ':'
517 && command
[3] == '\\') ||
518 (command
[0] == '\\' && command
[1] == '\\'))
522 // Split the command into an argv array.
523 for(const char* c
= command
; *c
;)
525 // Skip over whitespace.
526 while(*c
== ' ' || *c
== '\t')
533 // Parse a quoted argument.
535 while(*c
&& *c
!= '"')
548 // Parse a quoted argument.
550 while(*c
&& *c
!= '\'')
563 // Parse an unquoted argument.
564 while(*c
&& *c
!= ' ' && *c
!= '\t')
566 if(*c
== '\\' && !win_path
)
589 bool cmSystemTools::RunSingleCommand(std::vector
<cmStdString
>const& command
,
590 std::string
* output
,
591 int* retVal
, const char* dir
,
595 std::vector
<const char*> argv
;
596 for(std::vector
<cmStdString
>::const_iterator a
= command
.begin();
597 a
!= command
.end(); ++a
)
599 argv
.push_back(a
->c_str());
607 cmsysProcess
* cp
= cmsysProcess_New();
608 cmsysProcess_SetCommand(cp
, &*argv
.begin());
609 cmsysProcess_SetWorkingDirectory(cp
, dir
);
610 if(cmSystemTools::GetRunCommandHideConsole())
612 cmsysProcess_SetOption(cp
, cmsysProcess_Option_HideWindow
, 1);
614 cmsysProcess_SetTimeout(cp
, timeout
);
615 cmsysProcess_Execute(cp
);
617 std::vector
<char> tempOutput
;
620 if ( output
|| verbose
)
622 while(cmsysProcess_WaitForData(cp
, &data
, &length
, 0))
624 if(output
|| verbose
)
626 // Translate NULL characters in the output into valid text.
627 // Visual Studio 7 puts these characters in the output of its
629 for(int i
=0; i
< length
; ++i
)
639 tempOutput
.insert(tempOutput
.end(), data
, data
+length
);
643 cmSystemTools::Stdout(data
, length
);
648 cmsysProcess_WaitForExit(cp
, 0);
649 if ( output
&& tempOutput
.begin() != tempOutput
.end())
651 output
->append(&*tempOutput
.begin(), tempOutput
.size());
655 if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Exited
)
659 *retVal
= cmsysProcess_GetExitValue(cp
);
663 if ( cmsysProcess_GetExitValue(cp
) != 0 )
669 else if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Exception
)
671 const char* exception_str
= cmsysProcess_GetExceptionString(cp
);
674 std::cerr
<< exception_str
<< std::endl
;
678 output
->append(exception_str
, strlen(exception_str
));
682 else if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Error
)
684 const char* error_str
= cmsysProcess_GetErrorString(cp
);
687 std::cerr
<< error_str
<< std::endl
;
691 output
->append(error_str
, strlen(error_str
));
695 else if(cmsysProcess_GetState(cp
) == cmsysProcess_State_Expired
)
697 const char* error_str
= "Process terminated due to timeout\n";
700 std::cerr
<< error_str
<< std::endl
;
704 output
->append(error_str
, strlen(error_str
));
709 cmsysProcess_Delete(cp
);
713 bool cmSystemTools::RunSingleCommand(
721 if(s_DisableRunCommandOutput
)
726 std::vector
<cmStdString
> args
= cmSystemTools::ParseArguments(command
);
732 return cmSystemTools::RunSingleCommand(args
, output
,retVal
,
733 dir
, verbose
, timeout
);
735 bool cmSystemTools::RunCommand(const char* command
,
742 return cmSystemTools::RunCommand(command
, output
, dummy
,
743 dir
, verbose
, timeout
);
746 #if defined(WIN32) && !defined(__CYGWIN__)
747 #include "cmWin32ProcessExecution.h"
748 // use this for shell commands like echo and dir
749 bool RunCommandViaWin32(const char* command
,
756 #if defined(__BORLANDC__)
758 cmWin32ProcessExecution::
759 BorlandRunCommand(command
, dir
, output
,
762 cmSystemTools::GetRunCommandHideConsole());
763 #else // Visual studio
764 ::SetLastError(ERROR_SUCCESS
);
767 cmSystemTools::Error("No command specified");
770 cmWin32ProcessExecution resProc
;
771 if(cmSystemTools::GetRunCommandHideConsole())
773 resProc
.SetHideWindows(true);
776 if ( cmSystemTools::GetWindows9xComspecSubstitute() )
778 resProc
.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
780 if ( !resProc
.StartProcess(command
, dir
, verbose
) )
782 output
= resProc
.GetOutput();
785 cmSystemTools::Stdout(output
.c_str());
789 resProc
.Wait(timeout
);
790 output
= resProc
.GetOutput();
791 retVal
= resProc
.GetExitValue();
796 // use this for shell commands like echo and dir
797 bool RunCommandViaSystem(const char* command
,
803 std::cout
<< "@@ " << command
<< std::endl
;
805 std::string commandInDir
;
808 commandInDir
= "cd ";
809 commandInDir
+= cmSystemTools::ConvertToOutputPath(dir
);
810 commandInDir
+= " && ";
811 commandInDir
+= command
;
815 commandInDir
= command
;
817 command
= commandInDir
.c_str();
818 std::string commandToFile
= command
;
819 commandToFile
+= " > ";
820 std::string tempFile
;
821 tempFile
+= _tempnam(0, "cmake");
823 commandToFile
+= tempFile
;
824 retVal
= system(commandToFile
.c_str());
825 std::ifstream
fin(tempFile
.c_str());
830 std::string errormsg
= "RunCommand produced no output: command: \"";
833 errormsg
+= "\nOutput file: ";
834 errormsg
+= tempFile
;
835 cmSystemTools::Error(errormsg
.c_str());
838 cmSystemTools::RemoveFile(tempFile
.c_str());
841 bool multiLine
= false;
843 while(cmSystemTools::GetLineFromStream(fin
, line
))
853 cmSystemTools::RemoveFile(tempFile
.c_str());
857 #else // We have popen
859 // BeOS seems to return from a successful pclose() before the process has
860 // legitimately exited, or at least before SIGCHLD is thrown...the signal may
861 // come quite some time after pclose returns! This causes havoc with later
862 // parts of CMake that expect to catch the signal from other child processes,
863 // so we explicitly wait to catch it here. This should be safe to do with
864 // popen() so long as we don't actually collect the zombie process ourselves.
867 #undef SIGBUS // this is the same as SIGSEGV on BeOS and causes issues below.
868 static volatile bool beos_seen_signal
= false;
869 static void beos_popen_workaround(int sig
)
871 beos_seen_signal
= true;
875 bool RunCommandViaPopen(const char* command
,
882 // if only popen worked on windows.....
883 std::string commandInDir
;
886 commandInDir
= "cd \"";
888 commandInDir
+= "\" && ";
889 commandInDir
+= command
;
893 commandInDir
= command
;
896 commandInDir
+= " 2>&1";
898 command
= commandInDir
.c_str();
899 const int BUFFER_SIZE
= 4096;
900 char buffer
[BUFFER_SIZE
];
903 cmSystemTools::Stdout("running ");
904 cmSystemTools::Stdout(command
);
905 cmSystemTools::Stdout("\n");
911 beos_seen_signal
= false;
912 signal(SIGCHLD
, beos_popen_workaround
);
915 FILE* cpipe
= popen(command
, "r");
919 signal(SIGCHLD
, SIG_DFL
);
923 fgets(buffer
, BUFFER_SIZE
, cpipe
);
928 cmSystemTools::Stdout(buffer
);
932 fgets(buffer
, BUFFER_SIZE
, cpipe
);
935 retVal
= pclose(cpipe
);
938 for (int i
= 0; (!beos_seen_signal
) && (i
< 3); i
++)
940 ::sleep(1); // signals should interrupt this...
943 if (!beos_seen_signal
)
945 signal(SIGCHLD
, SIG_DFL
); // oh well, didn't happen. Go on anyhow.
949 if (WIFEXITED(retVal
))
951 retVal
= WEXITSTATUS(retVal
);
954 if (WIFSIGNALED(retVal
))
956 retVal
= WTERMSIG(retVal
);
957 cmOStringStream error
;
958 error
<< "\nProcess terminated due to ";
984 error
<< "signal " << retVal
;
987 output
+= error
.str();
992 #endif // endif WIN32 not CYGWIN
995 // run a command unix uses popen (easy)
996 // windows uses system and ShortPath
997 bool cmSystemTools::RunCommand(const char* command
,
1004 if(s_DisableRunCommandOutput
)
1009 #if defined(WIN32) && !defined(__CYGWIN__)
1010 // if the command does not start with a quote, then
1011 // try to find the program, and if the program can not be
1012 // found use system to run the command as it must be a built in
1013 // shell command like echo or dir
1015 if(command
[0] == '\"')
1017 // count the number of quotes
1018 for(const char* s
= command
; *s
!= 0; ++s
)
1029 // if there are more than two double quotes use
1030 // GetShortPathName, the cmd.exe program in windows which
1031 // is used by system fails to execute if there are more than
1032 // one set of quotes in the arguments
1035 cmsys::RegularExpression
quoted("^\"([^\"]*)\"[ \t](.*)");
1036 if(quoted
.find(command
))
1038 std::string shortCmd
;
1039 std::string cmd
= quoted
.match(1);
1040 std::string args
= quoted
.match(2);
1041 if(! cmSystemTools::FileExists(cmd
.c_str()) )
1045 else if(!cmSystemTools::GetShortPath(cmd
.c_str(), shortCmd
))
1047 cmSystemTools::Error("GetShortPath failed for " , cmd
.c_str());
1053 //return RunCommandViaSystem(shortCmd.c_str(), dir,
1054 // output, retVal, verbose);
1055 //return WindowsRunCommand(shortCmd.c_str(), dir,
1056 //output, retVal, verbose);
1057 return RunCommandViaWin32(shortCmd
.c_str(), dir
,
1058 output
, retVal
, verbose
, timeout
);
1062 cmSystemTools::Error("Could not parse command line with quotes ",
1067 // if there is only one set of quotes or no quotes then just run the command
1068 //return RunCommandViaSystem(command, dir, output, retVal, verbose);
1069 //return WindowsRunCommand(command, dir, output, retVal, verbose);
1070 return ::RunCommandViaWin32(command
, dir
, output
, retVal
, verbose
, timeout
);
1072 return ::RunCommandViaPopen(command
, dir
, output
, retVal
, verbose
, timeout
);
1076 bool cmSystemTools::DoesFileExistWithExtensions(
1078 const std::vector
<std::string
>& headerExts
)
1082 for( std::vector
<std::string
>::const_iterator ext
= headerExts
.begin();
1083 ext
!= headerExts
.end(); ++ext
)
1088 if(cmSystemTools::FileExists(hname
.c_str()))
1096 std::string
cmSystemTools::FileExistsInParentDirectories(const char* fname
,
1097 const char* directory
, const char* toplevel
)
1099 std::string file
= fname
;
1100 cmSystemTools::ConvertToUnixSlashes(file
);
1101 std::string dir
= directory
;
1102 cmSystemTools::ConvertToUnixSlashes(dir
);
1103 std::string prevDir
;
1104 while(dir
!= prevDir
)
1106 std::string path
= dir
+ "/" + file
;
1107 if ( cmSystemTools::FileExists(path
.c_str()) )
1111 if ( dir
.size() < strlen(toplevel
) )
1116 dir
= cmSystemTools::GetParentDirectory(dir
.c_str());
1121 bool cmSystemTools::cmCopyFile(const char* source
, const char* destination
)
1123 return Superclass::CopyFileAlways(source
, destination
);
1126 bool cmSystemTools::CopyFileIfDifferent(const char* source
,
1127 const char* destination
)
1129 return Superclass::CopyFileIfDifferent(source
, destination
);
1132 //----------------------------------------------------------------------------
1133 bool cmSystemTools::RenameFile(const char* oldname
, const char* newname
)
1136 /* On Windows the move functions will not replace existing files.
1137 Check if the destination exists. */
1138 struct stat newFile
;
1139 if(stat(newname
, &newFile
) == 0)
1141 /* The destination exists. We have to replace it carefully. The
1142 MoveFileEx function does what we need but is not available on
1147 /* Make sure the destination is not read only. */
1148 attrs
= GetFileAttributes(newname
);
1149 if(attrs
& FILE_ATTRIBUTE_READONLY
)
1151 SetFileAttributes(newname
, attrs
& ~FILE_ATTRIBUTE_READONLY
);
1154 /* Check the windows version number. */
1155 osv
.dwOSVersionInfoSize
= sizeof(osv
);
1157 if(osv
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)
1159 /* This is Win9x. There is no MoveFileEx implementation. We
1160 cannot quite rename the file atomically. Just delete the
1161 destination and then move the file. */
1162 DeleteFile(newname
);
1163 return MoveFile(oldname
, newname
) != 0;
1167 /* This is not Win9x. Use the MoveFileEx implementation. */
1168 return MoveFileEx(oldname
, newname
, MOVEFILE_REPLACE_EXISTING
) != 0;
1173 /* The destination does not exist. Just move the file. */
1174 return MoveFile(oldname
, newname
) != 0;
1177 /* On UNIX we have an OS-provided call to do this atomically. */
1178 return rename(oldname
, newname
) == 0;
1182 bool cmSystemTools::ComputeFileMD5(const char* source
, char* md5out
)
1184 #if defined(CMAKE_BUILD_WITH_CMAKE)
1185 if(!cmSystemTools::FileExists(source
))
1191 #if defined(_WIN32) || defined(__CYGWIN__)
1192 cmsys_ios::ifstream
fin(source
, cmsys_ios::ios::binary
| cmsys_ios::ios::in
);
1194 cmsys_ios::ifstream
fin(source
);
1201 cmsysMD5
* md5
= cmsysMD5_New();
1202 cmsysMD5_Initialize(md5
);
1204 // Should be efficient enough on most system:
1205 const int bufferSize
= 4096;
1206 char buffer
[bufferSize
];
1207 // This copy loop is very sensitive on certain platforms with
1208 // slightly broken stream libraries (like HPUX). Normally, it is
1209 // incorrect to not check the error condition on the fin.read()
1210 // before using the data, but the fin.gcount() will be zero if an
1211 // error occurred. Therefore, the loop should be safe everywhere.
1214 fin
.read(buffer
, bufferSize
);
1217 cmsysMD5_Append(md5
, reinterpret_cast<unsigned char const*>(buffer
),
1221 cmsysMD5_FinalizeHex(md5
, md5out
);
1222 cmsysMD5_Delete(md5
);
1229 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1234 std::string
cmSystemTools::ComputeStringMD5(const char* input
)
1236 #if defined(CMAKE_BUILD_WITH_CMAKE)
1238 cmsysMD5
* md5
= cmsysMD5_New();
1239 cmsysMD5_Initialize(md5
);
1240 cmsysMD5_Append(md5
, reinterpret_cast<unsigned char const*>(input
), -1);
1241 cmsysMD5_FinalizeHex(md5
, md5out
);
1242 cmsysMD5_Delete(md5
);
1243 return std::string(md5out
, 32);
1246 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1251 void cmSystemTools::Glob(const char *directory
, const char *regexp
,
1252 std::vector
<std::string
>& files
)
1255 cmsys::RegularExpression
reg(regexp
);
1257 if (d
.Load(directory
))
1261 numf
= d
.GetNumberOfFiles();
1262 for (i
= 0; i
< numf
; i
++)
1264 std::string fname
= d
.GetFile(i
);
1265 if (reg
.find(fname
))
1267 files
.push_back(fname
);
1274 void cmSystemTools::GlobDirs(const char *fullPath
,
1275 std::vector
<std::string
>& files
)
1277 std::string path
= fullPath
;
1278 std::string::size_type pos
= path
.find("/*");
1279 if(pos
== std::string::npos
)
1281 files
.push_back(fullPath
);
1284 std::string startPath
= path
.substr(0, pos
);
1285 std::string finishPath
= path
.substr(pos
+2);
1288 if (d
.Load(startPath
.c_str()))
1290 for (unsigned int i
= 0; i
< d
.GetNumberOfFiles(); ++i
)
1292 if((std::string(d
.GetFile(i
)) != ".")
1293 && (std::string(d
.GetFile(i
)) != ".."))
1295 std::string fname
= startPath
;
1297 fname
+= d
.GetFile(i
);
1298 if(cmSystemTools::FileIsDirectory(fname
.c_str()))
1300 fname
+= finishPath
;
1301 cmSystemTools::GlobDirs(fname
.c_str(), files
);
1309 void cmSystemTools::ExpandList(std::vector
<std::string
> const& arguments
,
1310 std::vector
<std::string
>& newargs
)
1312 std::vector
<std::string
>::const_iterator i
;
1313 for(i
= arguments
.begin();i
!= arguments
.end(); ++i
)
1315 cmSystemTools::ExpandListArgument(*i
, newargs
);
1319 void cmSystemTools::ExpandListArgument(const std::string
& arg
,
1320 std::vector
<std::string
>& newargs
,
1323 // If argument is empty, it is an empty list.
1324 if(arg
.length() == 0 && !emptyArgs
)
1328 // if there are no ; in the name then just copy the current string
1329 if(arg
.find(';') == std::string::npos
)
1331 newargs
.push_back(arg
);
1334 std::vector
<char> newArgVec
;
1335 // Break the string at non-escaped semicolons not nested in [].
1336 int squareNesting
= 0;
1337 for(const char* c
= arg
.c_str(); *c
; ++c
)
1343 // We only want to allow escaping of semicolons. Other
1344 // escapes should not be processed here.
1348 newArgVec
.push_back(*c
);
1352 newArgVec
.push_back('\\');
1355 newArgVec
.push_back(*c
);
1359 // Terminate the loop properly.
1367 newArgVec
.push_back(*c
);
1372 newArgVec
.push_back(*c
);
1376 // Break the string here if we are not nested inside square
1378 if(squareNesting
== 0)
1380 if ( newArgVec
.size() || emptyArgs
)
1382 // Add the last argument if the string is not empty.
1383 newArgVec
.push_back(0);
1384 newargs
.push_back(&*newArgVec
.begin());
1390 newArgVec
.push_back(*c
);
1395 // Just append this character.
1396 newArgVec
.push_back(*c
);
1400 if ( newArgVec
.size() || emptyArgs
)
1402 // Add the last argument if the string is not empty.
1403 newArgVec
.push_back(0);
1404 newargs
.push_back(&*newArgVec
.begin());
1408 bool cmSystemTools::SimpleGlob(const cmStdString
& glob
,
1409 std::vector
<cmStdString
>& files
,
1413 if ( glob
[glob
.size()-1] != '*' )
1417 std::string path
= cmSystemTools::GetFilenamePath(glob
);
1418 std::string ppath
= cmSystemTools::GetFilenameName(glob
);
1419 ppath
= ppath
.substr(0, ppath
.size()-1);
1420 if ( path
.size() == 0 )
1427 if (d
.Load(path
.c_str()))
1429 for (unsigned int i
= 0; i
< d
.GetNumberOfFiles(); ++i
)
1431 if((std::string(d
.GetFile(i
)) != ".")
1432 && (std::string(d
.GetFile(i
)) != ".."))
1434 std::string fname
= path
;
1435 if ( path
[path
.size()-1] != '/' )
1439 fname
+= d
.GetFile(i
);
1440 std::string sfname
= d
.GetFile(i
);
1441 if ( type
> 0 && cmSystemTools::FileIsDirectory(fname
.c_str()) )
1445 if ( type
< 0 && !cmSystemTools::FileIsDirectory(fname
.c_str()) )
1449 if ( sfname
.size() >= ppath
.size() &&
1450 sfname
.substr(0, ppath
.size()) ==
1453 files
.push_back(fname
);
1462 cmSystemTools::FileFormat
cmSystemTools::GetFileFormat(const char* cext
)
1464 if ( ! cext
|| *cext
== 0 )
1466 return cmSystemTools::NO_FILE_FORMAT
;
1468 //std::string ext = cmSystemTools::LowerCase(cext);
1469 std::string ext
= cext
;
1470 if ( ext
== "c" || ext
== ".c" ||
1471 ext
== "m" || ext
== ".m"
1472 ) { return cmSystemTools::C_FILE_FORMAT
; }
1474 ext
== "C" || ext
== ".C" ||
1475 ext
== "M" || ext
== ".M" ||
1476 ext
== "c++" || ext
== ".c++" ||
1477 ext
== "cc" || ext
== ".cc" ||
1478 ext
== "cpp" || ext
== ".cpp" ||
1479 ext
== "cxx" || ext
== ".cxx" ||
1480 ext
== "mm" || ext
== ".mm"
1481 ) { return cmSystemTools::CXX_FILE_FORMAT
; }
1483 ext
== "f" || ext
== ".f" ||
1484 ext
== "F" || ext
== ".F" ||
1485 ext
== "f77" || ext
== ".f77" ||
1486 ext
== "f90" || ext
== ".f90" ||
1487 ext
== "for" || ext
== ".for" ||
1488 ext
== "f95" || ext
== ".f95"
1489 ) { return cmSystemTools::FORTRAN_FILE_FORMAT
; }
1490 if ( ext
== "java" || ext
== ".java" )
1491 { return cmSystemTools::JAVA_FILE_FORMAT
; }
1493 ext
== "H" || ext
== ".H" ||
1494 ext
== "h" || ext
== ".h" ||
1495 ext
== "h++" || ext
== ".h++" ||
1496 ext
== "hm" || ext
== ".hm" ||
1497 ext
== "hpp" || ext
== ".hpp" ||
1498 ext
== "hxx" || ext
== ".hxx" ||
1499 ext
== "in" || ext
== ".in" ||
1500 ext
== "txx" || ext
== ".txx"
1501 ) { return cmSystemTools::HEADER_FILE_FORMAT
; }
1502 if ( ext
== "rc" || ext
== ".rc" )
1503 { return cmSystemTools::RESOURCE_FILE_FORMAT
; }
1504 if ( ext
== "def" || ext
== ".def" )
1505 { return cmSystemTools::DEFINITION_FILE_FORMAT
; }
1506 if ( ext
== "lib" || ext
== ".lib" ||
1507 ext
== "a" || ext
== ".a")
1508 { return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT
; }
1509 if ( ext
== "o" || ext
== ".o" ||
1510 ext
== "obj" || ext
== ".obj")
1511 { return cmSystemTools::OBJECT_FILE_FORMAT
; }
1513 if ( ext
== "dylib" || ext
== ".dylib" )
1514 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT
; }
1515 if ( ext
== "so" || ext
== ".so" ||
1516 ext
== "bundle" || ext
== ".bundle" )
1517 { return cmSystemTools::MODULE_FILE_FORMAT
; }
1519 if ( ext
== "so" || ext
== ".so" ||
1520 ext
== "sl" || ext
== ".sl" ||
1521 ext
== "dll" || ext
== ".dll" )
1522 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT
; }
1524 return cmSystemTools::UNKNOWN_FILE_FORMAT
;
1527 bool cmSystemTools::Split(const char* s
, std::vector
<cmStdString
>& l
)
1529 std::vector
<std::string
> temp
;
1530 bool res
= Superclass::Split(s
, temp
);
1531 for(std::vector
<std::string
>::const_iterator i
= temp
.begin();
1532 i
!= temp
.end(); ++i
)
1539 std::string
cmSystemTools::ConvertToOutputPath(const char* path
)
1541 #if defined(_WIN32) && !defined(__CYGWIN__)
1542 if(s_ForceUnixPaths
)
1544 return cmSystemTools::ConvertToUnixOutputPath(path
);
1546 return cmSystemTools::ConvertToWindowsOutputPath(path
);
1548 return cmSystemTools::ConvertToUnixOutputPath(path
);
1552 void cmSystemTools::ConvertToOutputSlashes(std::string
& path
)
1554 #if defined(_WIN32) && !defined(__CYGWIN__)
1555 if(!s_ForceUnixPaths
)
1557 // Convert to windows slashes.
1558 std::string::size_type pos
= 0;
1559 while((pos
= path
.find('/', pos
)) != std::string::npos
)
1565 static_cast<void>(path
);
1569 std::string
cmSystemTools::ConvertToRunCommandPath(const char* path
)
1571 #if defined(_WIN32) && !defined(__CYGWIN__)
1572 return cmSystemTools::ConvertToWindowsOutputPath(path
);
1574 return cmSystemTools::ConvertToUnixOutputPath(path
);
1578 bool cmSystemTools::StringEndsWith(const char* str1
, const char* str2
)
1580 if ( !str1
|| !str2
|| strlen(str1
) < strlen(str2
) )
1584 return !strncmp(str1
+ (strlen(str1
)-strlen(str2
)), str2
, strlen(str2
));
1587 // compute the relative path from here to there
1588 std::string
cmSystemTools::RelativePath(const char* local
, const char* remote
)
1590 if(!cmSystemTools::FileIsFullPath(local
))
1592 cmSystemTools::Error("RelativePath must be passed a full path to local: ",
1595 if(!cmSystemTools::FileIsFullPath(remote
))
1597 cmSystemTools::Error
1598 ("RelativePath must be passed a full path to remote: ", remote
);
1600 return cmsys::SystemTools::RelativePath(local
, remote
);
1603 #ifdef CMAKE_BUILD_WITH_CMAKE
1604 //----------------------------------------------------------------------
1605 bool cmSystemTools::UnsetEnv(const char* value
)
1607 #if !defined(HAVE_UNSETENV)
1608 std::string var
= value
;
1610 return cmSystemTools::PutEnv(var
.c_str());
1617 //----------------------------------------------------------------------
1618 std::vector
<std::string
> cmSystemTools::GetEnvironmentVariables()
1620 std::vector
<std::string
> env
;
1622 for ( cc
= 0; environ
[cc
]; ++ cc
)
1624 env
.push_back(environ
[cc
]);
1629 //----------------------------------------------------------------------
1630 std::vector
<std::string
> cmSystemTools::AppendEnv(
1631 std::vector
<std::string
>* env
)
1633 std::vector
<std::string
> origEnv
= GetEnvironmentVariables();
1635 if (env
&& env
->size()>0)
1637 std::vector
<std::string
>::const_iterator eit
;
1639 for (eit
= env
->begin(); eit
!= env
->end(); ++eit
)
1641 PutEnv(eit
->c_str());
1648 //----------------------------------------------------------------------
1649 void cmSystemTools::RestoreEnv(const std::vector
<std::string
>& env
)
1651 std::vector
<std::string
>::const_iterator eit
;
1653 // First clear everything in the current environment:
1655 std::vector
<std::string
> currentEnv
= GetEnvironmentVariables();
1656 for (eit
= currentEnv
.begin(); eit
!= currentEnv
.end(); ++eit
)
1658 std::string
var(*eit
);
1660 std::string::size_type pos
= var
.find("=");
1661 if (pos
!= std::string::npos
)
1663 var
= var
.substr(0, pos
);
1666 UnsetEnv(var
.c_str());
1669 // Then put back each entry from the original environment:
1671 for (eit
= env
.begin(); eit
!= env
.end(); ++eit
)
1673 PutEnv(eit
->c_str());
1678 void cmSystemTools::EnableVSConsoleOutput()
1680 // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
1681 // display output to the console unless this environment variable is
1682 // set. We need it to capture the output of these build tools.
1683 // Note for future work that one could pass "/out \\.\pipe\NAME" to
1684 // either of these executables where NAME is created with
1685 // CreateNamedPipe. This would bypass the internal buffering of the
1686 // output and allow it to be captured on the fly.
1688 cmSystemTools::PutEnv("vsconsoleoutput=1");
1692 bool cmSystemTools::IsPathToFramework(const char* path
)
1694 if(cmSystemTools::FileIsFullPath(path
))
1696 std::string libname
= path
;
1697 if(libname
.find(".framework") == libname
.size()+1-sizeof(".framework"))
1705 #if defined(CMAKE_BUILD_WITH_CMAKE)
1706 struct cmSystemToolsGZStruct
1712 int cmSystemToolsGZStructOpen(void* call_data
, const char *pathname
,
1713 int oflags
, mode_t mode
);
1714 int cmSystemToolsGZStructClose(void* call_data
);
1715 ssize_t
cmSystemToolsGZStructRead(void* call_data
, void* buf
, size_t count
);
1716 ssize_t
cmSystemToolsGZStructWrite(void* call_data
, const void* buf
,
1720 int cmSystemToolsGZStructOpen(void* call_data
, const char *pathname
,
1721 int oflags
, mode_t mode
)
1723 const char *gzoflags
;
1726 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1728 switch (oflags
& O_ACCMODE
)
1742 fd
= open(pathname
, oflags
, mode
);
1748 // no fchmod on BeOS 5...do pathname instead.
1749 #if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
1750 if ((oflags
& O_CREAT
) && chmod(pathname
, mode
))
1754 #elif !defined(_WIN32) || defined(__CYGWIN__)
1755 if ((oflags
& O_CREAT
) && fchmod(fd
, mode
))
1761 gzf
->GZFile
= gzdopen(fd
, gzoflags
);
1771 int cmSystemToolsGZStructClose(void* call_data
)
1773 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1774 return gzclose(gzf
->GZFile
);
1777 ssize_t
cmSystemToolsGZStructRead(void* call_data
, void* buf
, size_t count
)
1779 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1780 return gzread(gzf
->GZFile
, buf
, static_cast<int>(count
));
1783 ssize_t
cmSystemToolsGZStructWrite(void* call_data
, const void* buf
,
1786 cmSystemToolsGZStruct
* gzf
= static_cast<cmSystemToolsGZStruct
*>(call_data
);
1787 return gzwrite(gzf
->GZFile
, (void*)buf
, static_cast<int>(count
));
1792 bool cmSystemTools::CreateTar(const char* outFileName
,
1793 const std::vector
<cmStdString
>& files
,
1794 bool gzip
, bool verbose
)
1796 #if defined(CMAKE_BUILD_WITH_CMAKE)
1798 char buf
[TAR_MAXPATHLEN
];
1799 char pathname
[TAR_MAXPATHLEN
];
1800 cmSystemToolsGZStruct gzs
;
1802 tartype_t gztype
= {
1803 (openfunc_t
)cmSystemToolsGZStructOpen
,
1804 (closefunc_t
)cmSystemToolsGZStructClose
,
1805 (readfunc_t
)cmSystemToolsGZStructRead
,
1806 (writefunc_t
)cmSystemToolsGZStructWrite
,
1810 // Ok, this libtar is not const safe. for now use auto_ptr hack
1811 char* realName
= new char[ strlen(outFileName
) + 1 ];
1812 std::auto_ptr
<char> realNamePtr(realName
);
1813 strcpy(realName
, outFileName
);
1817 options
|= TAR_VERBOSE
;
1822 if (tar_open(&t
, realName
,
1823 (gzip
? &gztype
: NULL
),
1824 O_WRONLY
| O_CREAT
, 0644,
1827 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno
));
1831 std::vector
<cmStdString
>::const_iterator it
;
1832 for (it
= files
.begin(); it
!= files
.end(); ++ it
)
1834 strncpy(pathname
, it
->c_str(), sizeof(pathname
));
1835 pathname
[sizeof(pathname
)-1] = 0;
1836 strncpy(buf
, pathname
, sizeof(buf
));
1837 buf
[sizeof(buf
)-1] = 0;
1838 if (tar_append_tree(t
, buf
, pathname
) != 0)
1840 cmOStringStream ostr
;
1841 ostr
<< "Problem with tar_append_tree(\"" << buf
<< "\", \""
1842 << pathname
<< "\"): "
1844 cmSystemTools::Error(ostr
.str().c_str());
1850 if (tar_append_eof(t
) != 0)
1852 cmSystemTools::Error("Problem with tar_append_eof(): ", strerror(errno
));
1857 if (tar_close(t
) != 0)
1859 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno
));
1872 bool cmSystemTools::ExtractTar(const char* outFileName
,
1873 const std::vector
<cmStdString
>& files
,
1874 bool gzip
, bool verbose
)
1877 #if defined(CMAKE_BUILD_WITH_CMAKE)
1879 cmSystemToolsGZStruct gzs
;
1881 tartype_t gztype
= {
1882 cmSystemToolsGZStructOpen
,
1883 cmSystemToolsGZStructClose
,
1884 cmSystemToolsGZStructRead
,
1885 cmSystemToolsGZStructWrite
,
1889 // Ok, this libtar is not const safe. for now use auto_ptr hack
1890 char* realName
= new char[ strlen(outFileName
) + 1 ];
1891 std::auto_ptr
<char> realNamePtr(realName
);
1892 strcpy(realName
, outFileName
);
1893 if (tar_open(&t
, realName
,
1894 (gzip
? &gztype
: NULL
),
1900 (verbose
?TAR_VERBOSE
:0)
1903 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno
));
1907 if (tar_extract_all(t
, 0) != 0)
1909 cmSystemTools::Error("Problem with tar_extract_all(): ", strerror(errno
));
1913 if (tar_close(t
) != 0)
1915 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno
));
1927 bool cmSystemTools::ListTar(const char* outFileName
,
1928 std::vector
<cmStdString
>& files
, bool gzip
,
1931 #if defined(CMAKE_BUILD_WITH_CMAKE)
1933 cmSystemToolsGZStruct gzs
;
1935 tartype_t gztype
= {
1936 cmSystemToolsGZStructOpen
,
1937 cmSystemToolsGZStructClose
,
1938 cmSystemToolsGZStructRead
,
1939 cmSystemToolsGZStructWrite
,
1943 // Ok, this libtar is not const safe. for now use auto_ptr hack
1944 char* realName
= new char[ strlen(outFileName
) + 1 ];
1945 std::auto_ptr
<char> realNamePtr(realName
);
1946 strcpy(realName
, outFileName
);
1947 if (tar_open(&t
, realName
,
1948 (gzip
? &gztype
: NULL
),
1954 (verbose
?TAR_VERBOSE
:0)
1957 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno
));
1961 while ((th_read(t
)) == 0)
1963 const char* filename
= th_get_pathname(t
);
1964 files
.push_back(filename
);
1968 th_print_long_ls(t
);
1972 std::cout
<< filename
<< std::endl
;
1978 if (TH_ISREG(t
) && tar_skip_regfile(t
) != 0)
1980 cmSystemTools::Error("Problem with tar_skip_regfile(): ",
1986 if (tar_close(t
) != 0)
1988 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno
));
2001 int cmSystemTools::WaitForLine(cmsysProcess
* process
, std::string
& line
,
2003 std::vector
<char>& out
,
2004 std::vector
<char>& err
)
2007 std::vector
<char>::iterator outiter
= out
.begin();
2008 std::vector
<char>::iterator erriter
= err
.begin();
2011 // Check for a newline in stdout.
2012 for(;outiter
!= out
.end(); ++outiter
)
2014 if((*outiter
== '\r') && ((outiter
+1) == out
.end()))
2018 else if(*outiter
== '\n' || *outiter
== '\0')
2020 int length
= outiter
-out
.begin();
2021 if(length
> 1 && *(outiter
-1) == '\r')
2027 line
.append(&out
[0], length
);
2029 out
.erase(out
.begin(), outiter
+1);
2030 return cmsysProcess_Pipe_STDOUT
;
2034 // Check for a newline in stderr.
2035 for(;erriter
!= err
.end(); ++erriter
)
2037 if((*erriter
== '\r') && ((erriter
+1) == err
.end()))
2041 else if(*erriter
== '\n' || *erriter
== '\0')
2043 int length
= erriter
-err
.begin();
2044 if(length
> 1 && *(erriter
-1) == '\r')
2050 line
.append(&err
[0], length
);
2052 err
.erase(err
.begin(), erriter
+1);
2053 return cmsysProcess_Pipe_STDERR
;
2057 // No newlines found. Wait for more data from the process.
2060 int pipe
= cmsysProcess_WaitForData(process
, &data
, &length
, &timeout
);
2061 if(pipe
== cmsysProcess_Pipe_Timeout
)
2063 // Timeout has been exceeded.
2066 else if(pipe
== cmsysProcess_Pipe_STDOUT
)
2068 // Append to the stdout buffer.
2069 std::vector
<char>::size_type size
= out
.size();
2070 out
.insert(out
.end(), data
, data
+length
);
2071 outiter
= out
.begin()+size
;
2073 else if(pipe
== cmsysProcess_Pipe_STDERR
)
2075 // Append to the stderr buffer.
2076 std::vector
<char>::size_type size
= err
.size();
2077 err
.insert(err
.end(), data
, data
+length
);
2078 erriter
= err
.begin()+size
;
2080 else if(pipe
== cmsysProcess_Pipe_None
)
2082 // Both stdout and stderr pipes have broken. Return leftover data.
2085 line
.append(&out
[0], outiter
-out
.begin());
2086 out
.erase(out
.begin(), out
.end());
2087 return cmsysProcess_Pipe_STDOUT
;
2089 else if(!err
.empty())
2091 line
.append(&err
[0], erriter
-err
.begin());
2092 err
.erase(err
.begin(), err
.end());
2093 return cmsysProcess_Pipe_STDERR
;
2097 return cmsysProcess_Pipe_None
;
2103 void cmSystemTools::DoNotInheritStdPipes()
2106 // Check to see if we are attached to a console
2107 // if so, then do not stop the inherited pipes
2108 // or stdout and stderr will not show up in dos
2110 CONSOLE_SCREEN_BUFFER_INFO hOutInfo
;
2111 HANDLE hOut
= GetStdHandle(STD_OUTPUT_HANDLE
);
2112 if(GetConsoleScreenBufferInfo(hOut
, &hOutInfo
))
2117 HANDLE out
= GetStdHandle(STD_OUTPUT_HANDLE
);
2118 DuplicateHandle(GetCurrentProcess(), out
,
2119 GetCurrentProcess(), &out
, 0, FALSE
,
2120 DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE
);
2121 SetStdHandle(STD_OUTPUT_HANDLE
, out
);
2124 HANDLE out
= GetStdHandle(STD_ERROR_HANDLE
);
2125 DuplicateHandle(GetCurrentProcess(), out
,
2126 GetCurrentProcess(), &out
, 0, FALSE
,
2127 DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE
);
2128 SetStdHandle(STD_ERROR_HANDLE
, out
);
2133 //----------------------------------------------------------------------------
2134 bool cmSystemTools::CopyFileTime(const char* fromFile
, const char* toFile
)
2136 #if defined(_WIN32) && !defined(__CYGWIN__)
2137 cmSystemToolsWindowsHandle hFrom
=
2138 CreateFile(fromFile
, GENERIC_READ
, FILE_SHARE_READ
, 0,
2139 OPEN_EXISTING
, 0, 0);
2140 cmSystemToolsWindowsHandle hTo
=
2141 CreateFile(toFile
, GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
2146 FILETIME timeCreation
;
2147 FILETIME timeLastAccess
;
2148 FILETIME timeLastWrite
;
2149 if(!GetFileTime(hFrom
, &timeCreation
, &timeLastAccess
, &timeLastWrite
))
2153 if(!SetFileTime(hTo
, &timeCreation
, &timeLastAccess
, &timeLastWrite
))
2158 struct stat fromStat
;
2159 if(stat(fromFile
, &fromStat
) < 0)
2165 buf
.actime
= fromStat
.st_atime
;
2166 buf
.modtime
= fromStat
.st_mtime
;
2167 if(utime(toFile
, &buf
) < 0)
2175 //----------------------------------------------------------------------------
2176 cmSystemToolsFileTime
* cmSystemTools::FileTimeNew()
2178 return new cmSystemToolsFileTime
;
2181 //----------------------------------------------------------------------------
2182 void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime
* t
)
2187 //----------------------------------------------------------------------------
2188 bool cmSystemTools::FileTimeGet(const char* fname
, cmSystemToolsFileTime
* t
)
2190 #if defined(_WIN32) && !defined(__CYGWIN__)
2191 cmSystemToolsWindowsHandle h
=
2192 CreateFile(fname
, GENERIC_READ
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
2197 if(!GetFileTime(h
, &t
->timeCreation
, &t
->timeLastAccess
, &t
->timeLastWrite
))
2203 if(stat(fname
, &st
) < 0)
2207 t
->timeBuf
.actime
= st
.st_atime
;
2208 t
->timeBuf
.modtime
= st
.st_mtime
;
2213 //----------------------------------------------------------------------------
2214 bool cmSystemTools::FileTimeSet(const char* fname
, cmSystemToolsFileTime
* t
)
2216 #if defined(_WIN32) && !defined(__CYGWIN__)
2217 cmSystemToolsWindowsHandle h
=
2218 CreateFile(fname
, GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
2223 if(!SetFileTime(h
, &t
->timeCreation
, &t
->timeLastAccess
, &t
->timeLastWrite
))
2228 if(utime(fname
, &t
->timeBuf
) < 0)
2236 //----------------------------------------------------------------------------
2237 static std::string cmSystemToolsExecutableDirectory
;
2238 void cmSystemTools::FindExecutableDirectory(const char* argv0
)
2240 #if defined(_WIN32) && !defined(__CYGWIN__)
2241 (void)argv0
; // ignore this on windows
2242 char modulepath
[_MAX_PATH
];
2243 ::GetModuleFileName(NULL
, modulepath
, sizeof(modulepath
));
2244 cmSystemToolsExecutableDirectory
=
2245 cmSystemTools::GetFilenamePath(modulepath
);
2248 std::string errorMsg
;
2250 if(cmSystemTools::FindProgramPath(argv0
, exe
, errorMsg
))
2253 exe
= cmSystemTools::GetRealPath(exe
.c_str());
2254 cmSystemToolsExecutableDirectory
=
2255 cmSystemTools::GetFilenamePath(exe
.c_str());
2264 //----------------------------------------------------------------------------
2265 const char* cmSystemTools::GetExecutableDirectory()
2267 return cmSystemToolsExecutableDirectory
.c_str();
2270 //----------------------------------------------------------------------------
2271 #if defined(CMAKE_BUILD_WITH_CMAKE)
2272 void cmSystemTools::MakefileColorEcho(int color
, const char* message
,
2273 bool newline
, bool enabled
)
2275 // On some platforms (an MSYS prompt) cmsysTerminal may not be able
2276 // to determine whether the stream is displayed on a tty. In this
2277 // case it assumes no unless we tell it otherwise. Since we want
2278 // color messages to be displayed for users we will assume yes.
2279 // However, we can test for some situations when the answer is most
2281 int assumeTTY
= cmsysTerminal_Color_AssumeTTY
;
2282 if(cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
2283 cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
2284 cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE"))
2286 // Avoid printing color escapes during dashboard builds.
2292 cmsysTerminal_cfprintf(color
| assumeTTY
, stdout
, "%s%s",
2293 message
, newline
? "\n" : "");
2297 // Color is disabled. Print without color.
2298 fprintf(stdout
, "%s%s", message
, newline
? "\n" : "");
2303 //----------------------------------------------------------------------------
2304 bool cmSystemTools::GuessLibrarySOName(std::string
const& fullPath
,
2305 std::string
& soname
)
2307 // For ELF shared libraries use a real parser to get the correct
2309 #if defined(CMAKE_USE_ELF_PARSER)
2310 cmELF
elf(fullPath
.c_str());
2313 return elf
.GetSOName(soname
);
2317 // If the file is not a symlink we have no guess for its soname.
2318 if(!cmSystemTools::FileIsSymlink(fullPath
.c_str()))
2322 if(!cmSystemTools::ReadSymlink(fullPath
.c_str(), soname
))
2327 // If the symlink has a path component we have no guess for the soname.
2328 if(!cmSystemTools::GetFilenamePath(soname
).empty())
2333 // If the symlink points at an extended version of the same name
2334 // assume it is the soname.
2335 std::string name
= cmSystemTools::GetFilenameName(fullPath
);
2336 if(soname
.length() > name
.length() &&
2337 soname
.substr(0, name
.length()) == name
)
2344 //----------------------------------------------------------------------------
2345 #if defined(CMAKE_USE_ELF_PARSER)
2346 std::string::size_type
cmSystemToolsFindRPath(std::string
const& have
,
2347 std::string
const& want
)
2349 // Search for the desired rpath.
2350 std::string::size_type pos
= have
.find(want
);
2352 // If the path is not present we are done.
2353 if(pos
== std::string::npos
)
2358 // Build a regex to match a properly separated path instance.
2359 std::string regex_str
= "(^|:)(";
2360 for(std::string::const_iterator i
= want
.begin(); i
!= want
.end(); ++i
)
2363 if(!(('a' <= ch
&& ch
<= 'z') ||
2364 ('A' <= ch
&& ch
<= 'Z') ||
2365 ('0' <= ch
&& ch
<= '9')))
2367 // Escape the non-alphanumeric character.
2370 // Store the character.
2371 regex_str
.append(1, static_cast<char>(ch
));
2373 regex_str
+= ")(:|$)";
2375 // Look for the separated path.
2376 cmsys::RegularExpression
regex(regex_str
.c_str());
2377 if(regex
.find(have
))
2379 // Return the position of the path portion.
2380 return regex
.start(2);
2384 // The desired rpath was not found.
2385 return std::string::npos
;
2390 #if defined(CMAKE_USE_ELF_PARSER)
2391 struct cmSystemToolsRPathInfo
2393 unsigned long Position
;
2400 //----------------------------------------------------------------------------
2401 bool cmSystemTools::ChangeRPath(std::string
const& file
,
2402 std::string
const& oldRPath
,
2403 std::string
const& newRPath
,
2407 #if defined(CMAKE_USE_ELF_PARSER)
2413 cmSystemToolsRPathInfo rp
[2];
2415 // Parse the ELF binary.
2416 cmELF
elf(file
.c_str());
2418 // Get the RPATH and RUNPATH entries from it.
2420 cmELF::StringEntry
const* se
[2] = {0, 0};
2421 const char* se_name
[2] = {0, 0};
2422 if(cmELF::StringEntry
const* se_rpath
= elf
.GetRPath())
2424 se
[se_count
] = se_rpath
;
2425 se_name
[se_count
] = "RPATH";
2428 if(cmELF::StringEntry
const* se_runpath
= elf
.GetRunPath())
2430 se
[se_count
] = se_runpath
;
2431 se_name
[se_count
] = "RUNPATH";
2436 if(newRPath
.empty())
2438 // The new rpath is empty and there is no rpath anyway so it is
2446 *emsg
= "No valid ELF RPATH or RUNPATH entry exists in the file; ";
2447 *emsg
+= elf
.GetErrorMessage();
2453 for(int i
=0; i
< se_count
; ++i
)
2455 // If both RPATH and RUNPATH refer to the same string literal it
2456 // needs to be changed only once.
2457 if(rp_count
&& rp
[0].Position
== se
[i
]->Position
)
2462 // Make sure the current rpath contains the old rpath.
2463 std::string::size_type pos
=
2464 cmSystemToolsFindRPath(se
[i
]->Value
, oldRPath
);
2465 if(pos
== std::string::npos
)
2467 // If it contains the new rpath instead then it is okay.
2468 if(cmSystemToolsFindRPath(se
[i
]->Value
, newRPath
) != std::string::npos
)
2475 e
<< "The current " << se_name
[i
] << " is:\n"
2476 << " " << se
[i
]->Value
<< "\n"
2477 << "which does not contain:\n"
2478 << " " << oldRPath
<< "\n"
2479 << "as was expected.";
2485 // Store information about the entry in the file.
2486 rp
[rp_count
].Position
= se
[i
]->Position
;
2487 rp
[rp_count
].Size
= se
[i
]->Size
;
2488 rp
[rp_count
].Name
= se_name
[i
];
2490 // Construct the new value which preserves the part of the path
2491 // not being changed.
2492 rp
[rp_count
].Value
= se
[i
]->Value
.substr(0, pos
);
2493 rp
[rp_count
].Value
+= newRPath
;
2494 rp
[rp_count
].Value
+= se
[i
]->Value
.substr(pos
+oldRPath
.length(),
2497 // Make sure there is enough room to store the new rpath and at
2498 // least one null terminator.
2499 if(rp
[rp_count
].Size
< rp
[rp_count
].Value
.length()+1)
2503 *emsg
= "The replacement path is too long for the ";
2504 *emsg
+= se_name
[i
];
2510 // This entry is ready for update.
2515 // If no runtime path needs to be changed, we are done.
2522 // Open the file for update.
2523 std::ofstream
f(file
.c_str(),
2524 std::ios::in
| std::ios::out
| std::ios::binary
);
2529 *emsg
= "Error opening file for update.";
2534 // Store the new RPATH and RUNPATH strings.
2535 for(int i
=0; i
< rp_count
; ++i
)
2537 // Seek to the RPATH position.
2538 if(!f
.seekp(rp
[i
].Position
))
2542 *emsg
= "Error seeking to ";
2543 *emsg
+= rp
[i
].Name
;
2544 *emsg
+= " position.";
2549 // Write the new rpath. Follow it with enough null terminators to
2550 // fill the string table entry.
2552 for(unsigned long j
=rp
[i
].Value
.length(); j
< rp
[i
].Size
; ++j
)
2557 // Make sure it wrote correctly.
2562 *emsg
= "Error writing the new ";
2563 *emsg
+= rp
[i
].Name
;
2564 *emsg
+= " string to the file.";
2571 // Everything was updated successfully.
2587 //----------------------------------------------------------------------------
2588 bool cmSystemTools::RemoveRPath(std::string
const& file
, std::string
* emsg
,
2591 #if defined(CMAKE_USE_ELF_PARSER)
2597 unsigned long zeroPosition
[2] = {0,0};
2598 unsigned long zeroSize
[2] = {0,0};
2599 unsigned long bytesBegin
= 0;
2600 std::vector
<char> bytes
;
2602 // Parse the ELF binary.
2603 cmELF
elf(file
.c_str());
2605 // Get the RPATH and RUNPATH entries from it and sort them by index
2606 // in the dynamic section header.
2608 cmELF::StringEntry
const* se
[2] = {0, 0};
2609 if(cmELF::StringEntry
const* se_rpath
= elf
.GetRPath())
2611 se
[se_count
++] = se_rpath
;
2613 if(cmELF::StringEntry
const* se_runpath
= elf
.GetRunPath())
2615 se
[se_count
++] = se_runpath
;
2619 // There is no RPATH or RUNPATH anyway.
2622 if(se_count
== 2 && se
[1]->IndexInSection
< se
[0]->IndexInSection
)
2624 cmsys_stl::swap(se
[0], se
[1]);
2627 // Get the size of the dynamic section header.
2628 unsigned int count
= elf
.GetDynamicEntryCount();
2631 // This should happen only for invalid ELF files where a DT_NULL
2632 // appears before the end of the table.
2635 *emsg
= "DYNAMIC section contains a DT_NULL before the end.";
2640 // Save information about the string entries to be zeroed.
2641 zeroCount
= se_count
;
2642 for(int i
=0; i
< se_count
; ++i
)
2644 zeroPosition
[i
] = se
[i
]->Position
;
2645 zeroSize
[i
] = se
[i
]->Size
;
2648 // Get the range of file positions corresponding to each entry and
2649 // the rest of the table after them.
2650 unsigned long entryBegin
[3] = {0,0,0};
2651 unsigned long entryEnd
[2] = {0,0};
2652 for(int i
=0; i
< se_count
; ++i
)
2654 entryBegin
[i
] = elf
.GetDynamicEntryPosition(se
[i
]->IndexInSection
);
2655 entryEnd
[i
] = elf
.GetDynamicEntryPosition(se
[i
]->IndexInSection
+1);
2657 entryBegin
[se_count
] = elf
.GetDynamicEntryPosition(count
);
2659 // The data are to be written over the old table entries starting at
2660 // the first one being removed.
2661 bytesBegin
= entryBegin
[0];
2662 unsigned long bytesEnd
= entryBegin
[se_count
];
2664 // Allocate a buffer to hold the part of the file to be written.
2665 // Initialize it with zeros.
2666 bytes
.resize(bytesEnd
- bytesBegin
, 0);
2668 // Read the part of the DYNAMIC section header that will move.
2669 // The remainder of the buffer will be left with zeros which
2670 // represent a DT_NULL entry.
2671 char* data
= &bytes
[0];
2672 for(int i
=0; i
< se_count
; ++i
)
2674 // Read data between the entries being removed.
2675 unsigned long sz
= entryBegin
[i
+1] - entryEnd
[i
];
2676 if(sz
> 0 && !elf
.ReadBytes(entryEnd
[i
], sz
, data
))
2680 *emsg
= "Failed to read DYNAMIC section header.";
2688 // Open the file for update.
2689 std::ofstream
f(file
.c_str(),
2690 std::ios::in
| std::ios::out
| std::ios::binary
);
2695 *emsg
= "Error opening file for update.";
2700 // Write the new DYNAMIC table header.
2701 if(!f
.seekp(bytesBegin
))
2705 *emsg
= "Error seeking to DYNAMIC table header for RPATH.";
2709 if(!f
.write(&bytes
[0], bytes
.size()))
2713 *emsg
= "Error replacing DYNAMIC table header.";
2718 // Fill the RPATH and RUNPATH strings with zero bytes.
2719 for(int i
=0; i
< zeroCount
; ++i
)
2721 if(!f
.seekp(zeroPosition
[i
]))
2725 *emsg
= "Error seeking to RPATH position.";
2729 for(unsigned long j
=0; j
< zeroSize
[i
]; ++j
)
2737 *emsg
= "Error writing the empty rpath string to the file.";
2743 // Everything was updated successfully.
2757 //----------------------------------------------------------------------------
2758 bool cmSystemTools::CheckRPath(std::string
const& file
,
2759 std::string
const& newRPath
)
2761 #if defined(CMAKE_USE_ELF_PARSER)
2762 // Parse the ELF binary.
2763 cmELF
elf(file
.c_str());
2765 // Get the RPATH or RUNPATH entry from it.
2766 cmELF::StringEntry
const* se
= elf
.GetRPath();
2769 se
= elf
.GetRunPath();
2772 // Make sure the current rpath contains the new rpath.
2773 if(newRPath
.empty())
2783 cmSystemToolsFindRPath(se
->Value
, newRPath
) != std::string::npos
)