1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #if defined(_MSC_VER) && _MSC_VER < 1300
13 # define _WIN32_WINNT 0x0400 /* for wincrypt.h */
15 #include "cmSystemTools.h"
22 # include <malloc.h> /* for malloc/free on QNX */
24 #include <cmsys/Glob.hxx>
25 #include <cmsys/RegularExpression.hxx>
26 #include <cmsys/Directory.hxx>
27 #include <cmsys/System.h>
28 #if defined(CMAKE_BUILD_WITH_CMAKE)
29 # include "cmArchiveWrite.h"
30 # include <cm_libarchive.h>
31 # include <cmsys/Terminal.h>
33 #include <cmsys/stl/algorithm>
37 # include <wincrypt.h>
39 # include <sys/time.h>
40 # include <sys/types.h>
43 # include <sys/wait.h>
48 #if defined(_WIN32) && \
49 (defined(_MSC_VER) || defined(__WATCOMC__) || \
50 defined(__BORLANDC__) || defined(__MINGW32__))
54 #if defined(CMAKE_BUILD_WITH_CMAKE)
56 # include "cmCryptoHash.h"
59 #if defined(CMAKE_USE_ELF_PARSER)
63 class cmSystemToolsFileTime
66 #if defined(_WIN32) && !defined(__CYGWIN__)
67 FILETIME timeCreation;
68 FILETIME timeLastAccess;
69 FILETIME timeLastWrite;
71 struct utimbuf timeBuf;
75 #if defined(__sgi) && !defined(__GNUC__)
76 # pragma set woff 1375 /* base class destructor not virtual */
79 #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
80 // For GetEnvironmentVariables
82 extern __declspec( dllimport ) char** environ;
84 extern char** environ;
89 class cmSystemToolsWindowsHandle
92 cmSystemToolsWindowsHandle(HANDLE h): handle_(h) {}
93 ~cmSystemToolsWindowsHandle()
95 if(this->handle_ != INVALID_HANDLE_VALUE)
97 CloseHandle(this->handle_);
100 operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; }
101 bool operator !() const { return this->handle_ == INVALID_HANDLE_VALUE; }
102 operator HANDLE() const { return this->handle_; }
106 #elif defined(__APPLE__)
107 #include <crt_externs.h>
108 #define environ (*_NSGetEnviron())
111 bool cmSystemTools::s_RunCommandHideConsole = false;
112 bool cmSystemTools::s_DisableRunCommandOutput = false;
113 bool cmSystemTools::s_ErrorOccured = false;
114 bool cmSystemTools::s_FatalErrorOccured = false;
115 bool cmSystemTools::s_DisableMessages = false;
116 bool cmSystemTools::s_ForceUnixPaths = false;
118 std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com";
119 void cmSystemTools::SetWindows9xComspecSubstitute(const char* str)
123 cmSystemTools::s_Windows9xComspecSubstitute = str;
126 const char* cmSystemTools::GetWindows9xComspecSubstitute()
128 return cmSystemTools::s_Windows9xComspecSubstitute.c_str();
131 void (*cmSystemTools::s_ErrorCallback)(const char*, const char*,
133 void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*);
134 void* cmSystemTools::s_ErrorCallbackClientData = 0;
135 void* cmSystemTools::s_StdoutCallbackClientData = 0;
136 bool (*cmSystemTools::s_InterruptCallback)(void*);
137 void* cmSystemTools::s_InterruptCallbackClientData = 0;
139 // replace replace with with as many times as it shows up in source.
140 // write the result into source.
141 #if defined(_WIN32) && !defined(__CYGWIN__)
142 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view)
144 // Regular expression to match anything inside [...] that begins in HKEY.
145 // Note that there is a special rule for regular expressions to match a
146 // close square-bracket inside a list delimited by square brackets.
147 // The "[^]]" part of this expression will match any character except
148 // a close square-bracket. The ']' character must be the first in the
149 // list of characters inside the [^...] block of the expression.
150 cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
152 // check for black line or comment
153 while (regEntry.find(source))
155 // the arguments are the second match
156 std::string key = regEntry.match(1);
158 if (ReadRegistryValue(key.c_str(), val, view))
160 std::string reg = "[";
162 cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
166 std::string reg = "[";
168 cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
173 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64)
175 cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
176 while (regEntry.find(source))
178 // the arguments are the second match
179 std::string key = regEntry.match(1);
181 std::string reg = "[";
183 cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
189 std::string cmSystemTools::EscapeQuotes(const char* str)
191 std::string result = "";
192 for(const char* ch = str; *ch != '\0'; ++ch)
203 std::string cmSystemTools::TrimWhitespace(const std::string& s)
205 std::string::const_iterator start = s.begin();
206 while(start != s.end() && *start <= ' ')
208 if (start == s.end())
211 std::string::const_iterator stop = s.end()-1;
214 return std::string(start, stop+1);
217 void cmSystemTools::Error(const char* m1, const char* m2,
218 const char* m3, const char* m4)
220 std::string message = "CMake Error: ";
237 cmSystemTools::s_ErrorOccured = true;
238 cmSystemTools::Message(message.c_str(),"Error");
241 void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData)
243 s_InterruptCallback = f;
244 s_InterruptCallbackClientData = clientData;
247 bool cmSystemTools::GetInterruptFlag()
249 if(s_InterruptCallback)
251 return (*s_InterruptCallback)(s_InterruptCallbackClientData);
256 void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData)
259 s_ErrorCallbackClientData = clientData;
262 void cmSystemTools::SetStdoutCallback(StdoutCallback f, void* clientData)
264 s_StdoutCallback = f;
265 s_StdoutCallbackClientData = clientData;
268 void cmSystemTools::Stdout(const char* s)
272 (*s_StdoutCallback)(s, static_cast<int>(strlen(s)),
273 s_StdoutCallbackClientData);
282 void cmSystemTools::Stderr(const char* s, int length)
284 std::cerr.write(s, length);
288 void cmSystemTools::Stdout(const char* s, int length)
292 (*s_StdoutCallback)(s, length, s_StdoutCallbackClientData);
296 std::cout.write(s, length);
301 void cmSystemTools::Message(const char* m1, const char *title)
303 if(s_DisableMessages)
309 (*s_ErrorCallback)(m1, title, s_DisableMessages,
310 s_ErrorCallbackClientData);
315 std::cerr << m1 << std::endl << std::flush;
321 void cmSystemTools::ReportLastSystemError(const char* msg)
324 m += ": System Error: ";
325 m += Superclass::GetLastSystemError();
326 cmSystemTools::Error(m.c_str());
329 bool cmSystemTools::IsInternallyOn(const char* val)
335 std::basic_string<char> v = val;
337 for(std::basic_string<char>::iterator c = v.begin();
340 *c = static_cast<char>(toupper(*c));
342 return (v == "I_ON" || v == "i_on");
345 bool cmSystemTools::IsOn(const char* val)
351 std::basic_string<char> v = val;
353 for(std::basic_string<char>::iterator c = v.begin();
356 *c = static_cast<char>(toupper(*c));
358 return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y");
361 bool cmSystemTools::IsNOTFOUND(const char* val)
363 size_t len = strlen(val);
364 const char* notfound = "-NOTFOUND";
365 const size_t lenNotFound = 9;
366 if(len < lenNotFound-1)
370 if(len == lenNotFound-1)
372 return ( strcmp(val, "NOTFOUND") == 0);
374 return ((strncmp((val + (len - lenNotFound)), notfound, lenNotFound) == 0));
378 bool cmSystemTools::IsOff(const char* val)
380 if (!val || strlen(val) == 0)
384 std::basic_string<char> v = val;
386 for(std::basic_string<char>::iterator c = v.begin();
389 *c = static_cast<char>(toupper(*c));
391 return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" ||
392 v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE");
395 //----------------------------------------------------------------------------
396 void cmSystemTools::ParseWindowsCommandLine(const char* command,
397 std::vector<std::string>& args)
399 // See the MSDN document "Parsing C Command-Line Arguments" at
400 // http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx for rules
401 // of parsing the windows command line.
403 bool in_argument = false;
404 bool in_quotes = false;
407 for(const char* c = command;*c; ++c)
416 int backslash_pairs = backslashes >> 1;
417 int backslash_escaped = backslashes & 1;
418 arg.append(backslash_pairs, '\\');
420 if(backslash_escaped)
422 /* An odd number of backslashes precede this quote.
428 /* An even number of backslashes precede this quote.
429 It is not escaped. */
430 in_quotes = !in_quotes;
436 arg.append(backslashes, '\\');
458 arg.append(backslashes, '\\');
465 //----------------------------------------------------------------------------
466 class cmSystemToolsArgV
470 cmSystemToolsArgV(char** argv): ArgV(argv) {}
473 for(char** arg = this->ArgV; arg && *arg; ++arg)
479 void Store(std::vector<std::string>& args) const
481 for(char** arg = this->ArgV; arg && *arg; ++arg)
483 args.push_back(*arg);
486 void Store(std::vector<cmStdString>& args) const
488 for(char** arg = this->ArgV; arg && *arg; ++arg)
490 args.push_back(*arg);
495 //----------------------------------------------------------------------------
496 void cmSystemTools::ParseUnixCommandLine(const char* command,
497 std::vector<std::string>& args)
499 // Invoke the underlying parser.
500 cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
504 //----------------------------------------------------------------------------
505 void cmSystemTools::ParseUnixCommandLine(const char* command,
506 std::vector<cmStdString>& args)
508 // Invoke the underlying parser.
509 cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
513 std::string cmSystemTools::EscapeWindowsShellArgument(const char* arg,
516 char local_buffer[1024];
517 char* buffer = local_buffer;
518 int size = cmsysSystem_Shell_GetArgumentSizeForWindows(arg, shell_flags);
521 buffer = new char[size];
523 cmsysSystem_Shell_GetArgumentForWindows(arg, buffer, shell_flags);
524 std::string result(buffer);
525 if(buffer != local_buffer)
532 std::vector<cmStdString> cmSystemTools::ParseArguments(const char* command)
534 std::vector<cmStdString> args;
537 bool win_path = false;
539 if ((command[0] != '/' && command[1] == ':' && command[2] == '\\') ||
540 (command[0] == '\"' && command[1] != '/' && command[2] == ':'
541 && command[3] == '\\') ||
542 (command[0] == '\'' && command[1] != '/' && command[2] == ':'
543 && command[3] == '\\') ||
544 (command[0] == '\\' && command[1] == '\\'))
548 // Split the command into an argv array.
549 for(const char* c = command; *c;)
551 // Skip over whitespace.
552 while(*c == ' ' || *c == '\t')
559 // Parse a quoted argument.
561 while(*c && *c != '"')
574 // Parse a quoted argument.
576 while(*c && *c != '\'')
589 // Parse an unquoted argument.
590 while(*c && *c != ' ' && *c != '\t')
592 if(*c == '\\' && !win_path)
615 bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
616 std::string* output ,
617 int* retVal , const char* dir ,
618 OutputOption outputflag ,
621 std::vector<const char*> argv;
622 for(std::vector<cmStdString>::const_iterator a = command.begin();
623 a != command.end(); ++a)
625 argv.push_back(a->c_str());
633 cmsysProcess* cp = cmsysProcess_New();
634 cmsysProcess_SetCommand(cp, &*argv.begin());
635 cmsysProcess_SetWorkingDirectory(cp, dir);
636 if(cmSystemTools::GetRunCommandHideConsole())
638 cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
641 if (outputflag == OUTPUT_PASSTHROUGH)
643 cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
644 cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
647 cmsysProcess_SetTimeout(cp, timeout);
648 cmsysProcess_Execute(cp);
650 std::vector<char> tempOutput;
654 if(outputflag != OUTPUT_PASSTHROUGH && (output || outputflag != OUTPUT_NONE))
656 while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0)
658 if(output || outputflag != OUTPUT_NONE)
660 // Translate NULL characters in the output into valid text.
661 // Visual Studio 7 puts these characters in the output of its
663 for(int i=0; i < length; ++i)
673 tempOutput.insert(tempOutput.end(), data, data+length);
675 if(outputflag != OUTPUT_NONE)
677 if(outputflag == OUTPUT_MERGE)
679 cmSystemTools::Stdout(data, length);
683 if(pipe == cmsysProcess_Pipe_STDERR)
685 cmSystemTools::Stderr(data, length);
687 else if(pipe == cmsysProcess_Pipe_STDOUT)
689 cmSystemTools::Stdout(data, length);
696 cmsysProcess_WaitForExit(cp, 0);
697 if ( output && tempOutput.begin() != tempOutput.end())
699 output->append(&*tempOutput.begin(), tempOutput.size());
703 if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
707 *retVal = cmsysProcess_GetExitValue(cp);
711 if ( cmsysProcess_GetExitValue(cp) != 0 )
717 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
719 const char* exception_str = cmsysProcess_GetExceptionString(cp);
720 if ( outputflag != OUTPUT_NONE )
722 std::cerr << exception_str << std::endl;
726 output->append(exception_str, strlen(exception_str));
730 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
732 const char* error_str = cmsysProcess_GetErrorString(cp);
733 if ( outputflag != OUTPUT_NONE )
735 std::cerr << error_str << std::endl;
739 output->append(error_str, strlen(error_str));
743 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
745 const char* error_str = "Process terminated due to timeout\n";
746 if ( outputflag != OUTPUT_NONE )
748 std::cerr << error_str << std::endl;
752 output->append(error_str, strlen(error_str));
757 cmsysProcess_Delete(cp);
761 bool cmSystemTools::RunSingleCommand(
766 OutputOption outputflag,
769 if(s_DisableRunCommandOutput)
771 outputflag = OUTPUT_NONE;
774 std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
780 return cmSystemTools::RunSingleCommand(args, output,retVal,
781 dir, outputflag, timeout);
783 bool cmSystemTools::RunCommand(const char* command,
790 return cmSystemTools::RunCommand(command, output, dummy,
791 dir, verbose, timeout);
794 #if defined(WIN32) && !defined(__CYGWIN__)
795 #include "cmWin32ProcessExecution.h"
796 // use this for shell commands like echo and dir
797 bool RunCommandViaWin32(const char* command,
804 #if defined(__BORLANDC__)
806 cmWin32ProcessExecution::
807 BorlandRunCommand(command, dir, output,
810 cmSystemTools::GetRunCommandHideConsole());
811 #else // Visual studio
812 ::SetLastError(ERROR_SUCCESS);
815 cmSystemTools::Error("No command specified");
818 cmWin32ProcessExecution resProc;
819 if(cmSystemTools::GetRunCommandHideConsole())
821 resProc.SetHideWindows(true);
824 if ( cmSystemTools::GetWindows9xComspecSubstitute() )
826 resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
828 if ( !resProc.StartProcess(command, dir, verbose) )
830 output = resProc.GetOutput();
833 cmSystemTools::Stdout(output.c_str());
837 resProc.Wait(timeout);
838 output = resProc.GetOutput();
839 retVal = resProc.GetExitValue();
844 // use this for shell commands like echo and dir
845 bool RunCommandViaSystem(const char* command,
851 std::cout << "@@ " << command << std::endl;
853 std::string commandInDir;
856 commandInDir = "cd ";
857 commandInDir += cmSystemTools::ConvertToOutputPath(dir);
858 commandInDir += " && ";
859 commandInDir += command;
863 commandInDir = command;
865 command = commandInDir.c_str();
866 std::string commandToFile = command;
867 commandToFile += " > ";
868 std::string tempFile;
869 tempFile += _tempnam(0, "cmake");
871 commandToFile += tempFile;
872 retVal = system(commandToFile.c_str());
873 std::ifstream fin(tempFile.c_str());
878 std::string errormsg = "RunCommand produced no output: command: \"";
881 errormsg += "\nOutput file: ";
882 errormsg += tempFile;
883 cmSystemTools::Error(errormsg.c_str());
886 cmSystemTools::RemoveFile(tempFile.c_str());
889 bool multiLine = false;
891 while(cmSystemTools::GetLineFromStream(fin, line))
901 cmSystemTools::RemoveFile(tempFile.c_str());
905 #else // We have popen
907 // BeOS seems to return from a successful pclose() before the process has
908 // legitimately exited, or at least before SIGCHLD is thrown...the signal may
909 // come quite some time after pclose returns! This causes havoc with later
910 // parts of CMake that expect to catch the signal from other child processes,
911 // so we explicitly wait to catch it here. This should be safe to do with
912 // popen() so long as we don't actually collect the zombie process ourselves.
915 #undef SIGBUS // this is the same as SIGSEGV on BeOS and causes issues below.
916 static volatile bool beos_seen_signal = false;
917 static void beos_popen_workaround(int sig)
919 beos_seen_signal = true;
923 bool RunCommandViaPopen(const char* command,
930 // if only popen worked on windows.....
931 std::string commandInDir;
934 commandInDir = "cd \"";
936 commandInDir += "\" && ";
937 commandInDir += command;
941 commandInDir = command;
944 commandInDir += " 2>&1";
946 command = commandInDir.c_str();
947 const int BUFFER_SIZE = 4096;
948 char buffer[BUFFER_SIZE];
951 cmSystemTools::Stdout("running ");
952 cmSystemTools::Stdout(command);
953 cmSystemTools::Stdout("\n");
959 beos_seen_signal = false;
960 signal(SIGCHLD, beos_popen_workaround);
963 FILE* cpipe = popen(command, "r");
967 signal(SIGCHLD, SIG_DFL);
971 if (!fgets(buffer, BUFFER_SIZE, cpipe))
979 cmSystemTools::Stdout(buffer);
982 if(!fgets(buffer, BUFFER_SIZE, cpipe))
988 retVal = pclose(cpipe);
991 for (int i = 0; (!beos_seen_signal) && (i < 3); i++)
993 ::sleep(1); // signals should interrupt this...
996 if (!beos_seen_signal)
998 signal(SIGCHLD, SIG_DFL); // oh well, didn't happen. Go on anyhow.
1002 if (WIFEXITED(retVal))
1004 retVal = WEXITSTATUS(retVal);
1007 if (WIFSIGNALED(retVal))
1009 retVal = WTERMSIG(retVal);
1010 cmOStringStream error;
1011 error << "\nProcess terminated due to ";
1037 error << "signal " << retVal;
1040 output += error.str();
1045 #endif // endif WIN32 not CYGWIN
1048 // run a command unix uses popen (easy)
1049 // windows uses system and ShortPath
1050 bool cmSystemTools::RunCommand(const char* command,
1051 std::string& output,
1057 if(s_DisableRunCommandOutput)
1062 #if defined(WIN32) && !defined(__CYGWIN__)
1063 // if the command does not start with a quote, then
1064 // try to find the program, and if the program can not be
1065 // found use system to run the command as it must be a built in
1066 // shell command like echo or dir
1068 if(command[0] == '\"')
1070 // count the number of quotes
1071 for(const char* s = command; *s != 0; ++s)
1082 // if there are more than two double quotes use
1083 // GetShortPathName, the cmd.exe program in windows which
1084 // is used by system fails to execute if there are more than
1085 // one set of quotes in the arguments
1088 cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
1089 if(quoted.find(command))
1091 std::string shortCmd;
1092 std::string cmd = quoted.match(1);
1093 std::string args = quoted.match(2);
1094 if(! cmSystemTools::FileExists(cmd.c_str()) )
1098 else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd))
1100 cmSystemTools::Error("GetShortPath failed for " , cmd.c_str());
1106 //return RunCommandViaSystem(shortCmd.c_str(), dir,
1107 // output, retVal, verbose);
1108 //return WindowsRunCommand(shortCmd.c_str(), dir,
1109 //output, retVal, verbose);
1110 return RunCommandViaWin32(shortCmd.c_str(), dir,
1111 output, retVal, verbose, timeout);
1115 cmSystemTools::Error("Could not parse command line with quotes ",
1120 // if there is only one set of quotes or no quotes then just run the command
1121 //return RunCommandViaSystem(command, dir, output, retVal, verbose);
1122 //return WindowsRunCommand(command, dir, output, retVal, verbose);
1123 return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout);
1125 return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout);
1129 bool cmSystemTools::DoesFileExistWithExtensions(
1131 const std::vector<std::string>& headerExts)
1135 for( std::vector<std::string>::const_iterator ext = headerExts.begin();
1136 ext != headerExts.end(); ++ext )
1141 if(cmSystemTools::FileExists(hname.c_str()))
1149 std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
1150 const char* directory, const char* toplevel)
1152 std::string file = fname;
1153 cmSystemTools::ConvertToUnixSlashes(file);
1154 std::string dir = directory;
1155 cmSystemTools::ConvertToUnixSlashes(dir);
1156 std::string prevDir;
1157 while(dir != prevDir)
1159 std::string path = dir + "/" + file;
1160 if ( cmSystemTools::FileExists(path.c_str()) )
1164 if ( dir.size() < strlen(toplevel) )
1169 dir = cmSystemTools::GetParentDirectory(dir.c_str());
1174 bool cmSystemTools::cmCopyFile(const char* source, const char* destination)
1176 return Superclass::CopyFileAlways(source, destination);
1179 bool cmSystemTools::CopyFileIfDifferent(const char* source,
1180 const char* destination)
1182 return Superclass::CopyFileIfDifferent(source, destination);
1185 //----------------------------------------------------------------------------
1186 bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
1189 # ifndef INVALID_FILE_ATTRIBUTES
1190 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
1192 /* Windows MoveFileEx may not replace read-only or in-use files. If it
1193 fails then remove the read-only attribute from any existing destination.
1194 Try multiple times since we may be racing against another process
1195 creating/opening the destination file just before our MoveFileEx. */
1197 while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries)
1199 // Try again only if failure was due to access permissions.
1200 if(GetLastError() != ERROR_ACCESS_DENIED)
1204 DWORD attrs = GetFileAttributes(newname);
1205 if((attrs != INVALID_FILE_ATTRIBUTES) &&
1206 (attrs & FILE_ATTRIBUTE_READONLY))
1208 // Remove the read-only attribute from the destination file.
1209 SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
1213 // The file may be temporarily in use so wait a bit.
1214 cmSystemTools::Delay(100);
1219 /* On UNIX we have an OS-provided call to do this atomically. */
1220 return rename(oldname, newname) == 0;
1224 bool cmSystemTools::ComputeFileMD5(const char* source, char* md5out)
1226 #if defined(CMAKE_BUILD_WITH_CMAKE)
1227 cmCryptoHashMD5 md5;
1228 std::string str = md5.HashFile(source);
1229 strncpy(md5out, str.c_str(), 32);
1230 return !str.empty();
1234 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1239 std::string cmSystemTools::ComputeStringMD5(const char* input)
1241 #if defined(CMAKE_BUILD_WITH_CMAKE)
1242 cmCryptoHashMD5 md5;
1243 return md5.HashString(input);
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 std::string cmSystemTools::CollapseCombinedPath(std::string const& dir,
1604 std::string const& file)
1606 if(dir.empty() || dir == ".")
1611 std::vector<std::string> dirComponents;
1612 std::vector<std::string> fileComponents;
1613 cmSystemTools::SplitPath(dir.c_str(), dirComponents);
1614 cmSystemTools::SplitPath(file.c_str(), fileComponents);
1616 if(fileComponents.empty())
1620 if(fileComponents[0] != "")
1622 // File is not a relative path.
1626 std::vector<std::string>::iterator i = fileComponents.begin()+1;
1627 while(i != fileComponents.end() && *i == ".." && dirComponents.size() > 1)
1629 ++i; // Remove ".." file component.
1630 dirComponents.pop_back(); // Remove last dir component.
1633 dirComponents.insert(dirComponents.end(), i, fileComponents.end());
1634 return cmSystemTools::JoinPath(dirComponents);
1637 #ifdef CMAKE_BUILD_WITH_CMAKE
1638 //----------------------------------------------------------------------
1639 bool cmSystemTools::UnsetEnv(const char* value)
1641 #if !defined(HAVE_UNSETENV)
1642 std::string var = value;
1644 return cmSystemTools::PutEnv(var.c_str());
1651 //----------------------------------------------------------------------
1652 std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
1654 std::vector<std::string> env;
1656 for ( cc = 0; environ[cc]; ++ cc )
1658 env.push_back(environ[cc]);
1663 //----------------------------------------------------------------------
1664 void cmSystemTools::AppendEnv(std::vector<std::string> const& env)
1666 for(std::vector<std::string>::const_iterator eit = env.begin();
1667 eit != env.end(); ++eit)
1669 cmSystemTools::PutEnv(eit->c_str());
1673 //----------------------------------------------------------------------
1674 cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
1676 this->Env = cmSystemTools::GetEnvironmentVariables();
1679 //----------------------------------------------------------------------
1680 cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
1682 // First clear everything in the current environment:
1683 std::vector<std::string> currentEnv = GetEnvironmentVariables();
1684 for(std::vector<std::string>::const_iterator
1685 eit = currentEnv.begin(); eit != currentEnv.end(); ++eit)
1687 std::string var(*eit);
1689 std::string::size_type pos = var.find("=");
1690 if (pos != std::string::npos)
1692 var = var.substr(0, pos);
1695 cmSystemTools::UnsetEnv(var.c_str());
1698 // Then put back each entry from the original environment:
1699 cmSystemTools::AppendEnv(this->Env);
1703 void cmSystemTools::EnableVSConsoleOutput()
1706 // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
1707 // display output to the console unless this environment variable is
1708 // set. We need it to capture the output of these build tools.
1709 // Note for future work that one could pass "/out \\.\pipe\NAME" to
1710 // either of these executables where NAME is created with
1711 // CreateNamedPipe. This would bypass the internal buffering of the
1712 // output and allow it to be captured on the fly.
1713 cmSystemTools::PutEnv("vsconsoleoutput=1");
1715 # ifdef CMAKE_BUILD_WITH_CMAKE
1716 // VS sets an environment variable to tell MS tools like "cl" to report
1717 // output through a backdoor pipe instead of stdout/stderr. Unset the
1718 // environment variable to close this backdoor for any path of process
1719 // invocations that passes through CMake so we can capture the output.
1720 cmSystemTools::UnsetEnv("VS_UNICODE_OUTPUT");
1725 bool cmSystemTools::IsPathToFramework(const char* path)
1727 if(cmSystemTools::FileIsFullPath(path))
1729 std::string libname = path;
1730 if(libname.find(".framework") == libname.size()+1-sizeof(".framework"))
1738 bool cmSystemTools::CreateTar(const char* outFileName,
1739 const std::vector<cmStdString>& files,
1740 bool gzip, bool bzip2, bool verbose)
1742 #if defined(CMAKE_BUILD_WITH_CMAKE)
1743 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1744 std::ofstream fout(outFileName, std::ios::out | cmsys_ios_binary);
1747 std::string e = "Cannot open output file \"";
1750 e += cmSystemTools::GetLastSystemError();
1751 cmSystemTools::Error(e.c_str());
1754 cmArchiveWrite a(fout, (gzip? cmArchiveWrite::CompressGZip :
1755 (bzip2? cmArchiveWrite::CompressBZip2 :
1756 cmArchiveWrite::CompressNone)),
1757 cmArchiveWrite::TypeTAR);
1758 a.SetVerbose(verbose);
1759 for(std::vector<cmStdString>::const_iterator i = files.begin();
1760 i != files.end(); ++i)
1762 std::string path = *i;
1763 if(cmSystemTools::FileIsFullPath(path.c_str()))
1765 // Get the relative path to the file.
1766 path = cmSystemTools::RelativePath(cwd.c_str(), path.c_str());
1775 cmSystemTools::Error(a.GetError().c_str());
1788 #if defined(CMAKE_BUILD_WITH_CMAKE)
1790 #define BSDTAR_FILESIZE_PRINTF "%lu"
1791 #define BSDTAR_FILESIZE_TYPE unsigned long
1793 list_item_verbose(FILE *out, struct archive_entry *entry)
1802 size_t gs_width = 13;
1805 * We avoid collecting the entire list in memory at once by
1806 * listing things as we see them. However, that also means we can't
1807 * just pre-compute the field widths. Instead, we start with guesses
1808 * and just widen them as necessary. These numbers are completely
1815 fprintf(out, "%s %d ",
1816 archive_entry_strmode(entry),
1817 archive_entry_nlink(entry));
1819 /* Use uname if it's present, else uid. */
1820 p = archive_entry_uname(entry);
1821 if ((p == NULL) || (*p == '\0'))
1823 sprintf(tmp, "%lu ",
1824 (unsigned long)archive_entry_uid(entry));
1832 fprintf(out, "%-*s ", (int)u_width, p);
1833 /* Use gname if it's present, else gid. */
1834 p = archive_entry_gname(entry);
1835 if (p != NULL && p[0] != '\0')
1837 fprintf(out, "%s", p);
1843 (unsigned long)archive_entry_gid(entry));
1845 fprintf(out, "%s", tmp);
1849 * Print device number or file size, right-aligned so as to make
1850 * total width of group and devnum/filesize fields be gs_width.
1851 * If gs_width is too small, grow it.
1853 if (archive_entry_filetype(entry) == AE_IFCHR
1854 || archive_entry_filetype(entry) == AE_IFBLK)
1856 sprintf(tmp, "%lu,%lu",
1857 (unsigned long)archive_entry_rdevmajor(entry),
1858 (unsigned long)archive_entry_rdevminor(entry));
1863 * Note the use of platform-dependent macros to format
1864 * the filesize here. We need the format string and the
1865 * corresponding type for the cast.
1867 sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
1868 (BSDTAR_FILESIZE_TYPE)archive_entry_size(entry));
1870 if (w + strlen(tmp) >= gs_width)
1872 gs_width = w+strlen(tmp)+1;
1874 fprintf(out, "%*s", (int)(gs_width - w), tmp);
1876 /* Format the time using 'ls -l' conventions. */
1877 tim = archive_entry_mtime(entry);
1878 #define HALF_YEAR (time_t)365 * 86400 / 2
1879 #if defined(_WIN32) && !defined(__CYGWIN__)
1880 /* Windows' strftime function does not support %e format. */
1881 #define DAY_FMT "%d"
1883 #define DAY_FMT "%e" /* Day number without leading zeros */
1885 if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
1887 fmt = DAY_FMT " %b %Y";
1891 fmt = DAY_FMT " %b %H:%M";
1893 strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
1894 fprintf(out, " %s ", tmp);
1895 fprintf(out, "%s", archive_entry_pathname(entry));
1897 /* Extra information for links. */
1898 if (archive_entry_hardlink(entry)) /* Hard link */
1900 fprintf(out, " link to %s",
1901 archive_entry_hardlink(entry));
1903 else if (archive_entry_symlink(entry)) /* Symbolic link */
1905 fprintf(out, " -> %s", archive_entry_symlink(entry));
1909 # pragma warn -8066 /* unreachable code */
1912 long copy_data(struct archive *ar, struct archive *aw)
1917 #if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
1918 __LA_INT64_T offset;
1925 r = archive_read_data_block(ar, &buff, &size, &offset);
1926 if (r == ARCHIVE_EOF)
1928 return (ARCHIVE_OK);
1930 if (r != ARCHIVE_OK)
1934 r = archive_write_data_block(aw, buff, size, offset);
1935 if (r != ARCHIVE_OK)
1937 cmSystemTools::Message("archive_write_data_block()",
1938 archive_error_string(aw));
1945 bool extract_tar(const char* outFileName, bool verbose,
1948 struct archive* a = archive_read_new();
1949 struct archive *ext = archive_write_disk_new();
1950 archive_read_support_compression_all(a);
1951 archive_read_support_format_all(a);
1952 struct archive_entry *entry;
1953 int r = archive_read_open_file(a, outFileName, 10240);
1956 cmSystemTools::Error("Problem with archive_read_open_file(): ",
1957 archive_error_string(a));
1962 r = archive_read_next_header(a, &entry);
1963 if (r == ARCHIVE_EOF)
1967 if (r != ARCHIVE_OK)
1969 cmSystemTools::Error("Problem with archive_read_next_header(): ",
1970 archive_error_string(a));
1973 if (verbose && extract)
1975 cmSystemTools::Stdout("x ");
1976 cmSystemTools::Stdout(archive_entry_pathname(entry));
1978 if(verbose && !extract)
1980 list_item_verbose(stdout, entry);
1984 cmSystemTools::Stdout(archive_entry_pathname(entry));
1988 r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME);
1989 if (r != ARCHIVE_OK)
1991 cmSystemTools::Error(
1992 "Problem with archive_write_disk_set_options(): ",
1993 archive_error_string(ext));
1997 r = archive_write_header(ext, entry);
1998 if (r != ARCHIVE_OK)
2000 cmSystemTools::Error("Problem with archive_write_header(): ",
2001 archive_error_string(ext));
2002 cmSystemTools::Error("Current file: ",
2003 archive_entry_pathname(entry));
2009 r = archive_write_finish_entry(ext);
2010 if (r != ARCHIVE_OK)
2012 cmSystemTools::Error("Problem with archive_write_finish_entry(): ",
2013 archive_error_string(ext));
2018 if (verbose || !extract)
2020 cmSystemTools::Stdout("\n");
2023 archive_read_close(a);
2024 archive_read_finish(a);
2025 return r == ARCHIVE_EOF || r == ARCHIVE_OK;
2030 bool cmSystemTools::ExtractTar(const char* outFileName,
2031 bool , bool verbose)
2033 #if defined(CMAKE_BUILD_WITH_CMAKE)
2034 return extract_tar(outFileName, verbose, true);
2042 bool cmSystemTools::ListTar(const char* outFileName,
2046 #if defined(CMAKE_BUILD_WITH_CMAKE)
2047 return extract_tar(outFileName, verbose, false);
2055 int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
2057 std::vector<char>& out,
2058 std::vector<char>& err)
2061 std::vector<char>::iterator outiter = out.begin();
2062 std::vector<char>::iterator erriter = err.begin();
2065 // Check for a newline in stdout.
2066 for(;outiter != out.end(); ++outiter)
2068 if((*outiter == '\r') && ((outiter+1) == out.end()))
2072 else if(*outiter == '\n' || *outiter == '\0')
2074 std::vector<char>::size_type length = outiter-out.begin();
2075 if(length > 1 && *(outiter-1) == '\r')
2081 line.append(&out[0], length);
2083 out.erase(out.begin(), outiter+1);
2084 return cmsysProcess_Pipe_STDOUT;
2088 // Check for a newline in stderr.
2089 for(;erriter != err.end(); ++erriter)
2091 if((*erriter == '\r') && ((erriter+1) == err.end()))
2095 else if(*erriter == '\n' || *erriter == '\0')
2097 std::vector<char>::size_type length = erriter-err.begin();
2098 if(length > 1 && *(erriter-1) == '\r')
2104 line.append(&err[0], length);
2106 err.erase(err.begin(), erriter+1);
2107 return cmsysProcess_Pipe_STDERR;
2111 // No newlines found. Wait for more data from the process.
2114 int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
2115 if(pipe == cmsysProcess_Pipe_Timeout)
2117 // Timeout has been exceeded.
2120 else if(pipe == cmsysProcess_Pipe_STDOUT)
2122 // Append to the stdout buffer.
2123 std::vector<char>::size_type size = out.size();
2124 out.insert(out.end(), data, data+length);
2125 outiter = out.begin()+size;
2127 else if(pipe == cmsysProcess_Pipe_STDERR)
2129 // Append to the stderr buffer.
2130 std::vector<char>::size_type size = err.size();
2131 err.insert(err.end(), data, data+length);
2132 erriter = err.begin()+size;
2134 else if(pipe == cmsysProcess_Pipe_None)
2136 // Both stdout and stderr pipes have broken. Return leftover data.
2139 line.append(&out[0], outiter-out.begin());
2140 out.erase(out.begin(), out.end());
2141 return cmsysProcess_Pipe_STDOUT;
2143 else if(!err.empty())
2145 line.append(&err[0], erriter-err.begin());
2146 err.erase(err.begin(), err.end());
2147 return cmsysProcess_Pipe_STDERR;
2151 return cmsysProcess_Pipe_None;
2157 void cmSystemTools::DoNotInheritStdPipes()
2160 // Check to see if we are attached to a console
2161 // if so, then do not stop the inherited pipes
2162 // or stdout and stderr will not show up in dos
2164 CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
2165 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
2166 if(GetConsoleScreenBufferInfo(hOut, &hOutInfo))
2171 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
2172 DuplicateHandle(GetCurrentProcess(), out,
2173 GetCurrentProcess(), &out, 0, FALSE,
2174 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2175 SetStdHandle(STD_OUTPUT_HANDLE, out);
2178 HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
2179 DuplicateHandle(GetCurrentProcess(), out,
2180 GetCurrentProcess(), &out, 0, FALSE,
2181 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2182 SetStdHandle(STD_ERROR_HANDLE, out);
2187 //----------------------------------------------------------------------------
2188 bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
2190 #if defined(_WIN32) && !defined(__CYGWIN__)
2191 cmSystemToolsWindowsHandle hFrom =
2192 CreateFile(fromFile, GENERIC_READ, FILE_SHARE_READ, 0,
2193 OPEN_EXISTING, 0, 0);
2194 cmSystemToolsWindowsHandle hTo =
2195 CreateFile(toFile, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2200 FILETIME timeCreation;
2201 FILETIME timeLastAccess;
2202 FILETIME timeLastWrite;
2203 if(!GetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite))
2207 if(!SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite))
2212 struct stat fromStat;
2213 if(stat(fromFile, &fromStat) < 0)
2219 buf.actime = fromStat.st_atime;
2220 buf.modtime = fromStat.st_mtime;
2221 if(utime(toFile, &buf) < 0)
2229 //----------------------------------------------------------------------------
2230 cmSystemToolsFileTime* cmSystemTools::FileTimeNew()
2232 return new cmSystemToolsFileTime;
2235 //----------------------------------------------------------------------------
2236 void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime* t)
2241 //----------------------------------------------------------------------------
2242 bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
2244 #if defined(_WIN32) && !defined(__CYGWIN__)
2245 cmSystemToolsWindowsHandle h =
2246 CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
2251 if(!GetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2257 if(stat(fname, &st) < 0)
2261 t->timeBuf.actime = st.st_atime;
2262 t->timeBuf.modtime = st.st_mtime;
2267 //----------------------------------------------------------------------------
2268 bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
2270 #if defined(_WIN32) && !defined(__CYGWIN__)
2271 cmSystemToolsWindowsHandle h =
2272 CreateFile(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2277 if(!SetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2282 if(utime(fname, &t->timeBuf) < 0)
2290 //----------------------------------------------------------------------------
2292 # ifndef CRYPT_SILENT
2293 # define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header. */
2295 static int WinCryptRandom(void* data, size_t size)
2298 HCRYPTPROV hProvider = 0;
2299 if(CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
2300 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
2302 result = CryptGenRandom(hProvider, (DWORD)size, (BYTE*)data)? 1:0;
2303 CryptReleaseContext(hProvider, 0);
2309 //----------------------------------------------------------------------------
2310 unsigned int cmSystemTools::RandomSeed()
2312 #if defined(_WIN32) && !defined(__CYGWIN__)
2313 unsigned int seed = 0;
2315 // Try using a real random source.
2316 if(WinCryptRandom(&seed, sizeof(seed)))
2321 // Fall back to the time and pid.
2323 GetSystemTimeAsFileTime(&ft);
2324 unsigned int t1 = static_cast<unsigned int>(ft.dwHighDateTime);
2325 unsigned int t2 = static_cast<unsigned int>(ft.dwLowDateTime);
2326 unsigned int pid = static_cast<unsigned int>(GetCurrentProcessId());
2327 return t1 ^ t2 ^ pid;
2331 unsigned int integer;
2332 char bytes[sizeof(unsigned int)];
2335 // Try using a real random source.
2336 std::ifstream fin("/dev/urandom");
2337 if(fin && fin.read(seed.bytes, sizeof(seed)) &&
2338 fin.gcount() == sizeof(seed))
2340 return seed.integer;
2343 // Fall back to the time and pid.
2345 gettimeofday(&t, 0);
2346 unsigned int pid = static_cast<unsigned int>(getpid());
2347 unsigned int tv_sec = static_cast<unsigned int>(t.tv_sec);
2348 unsigned int tv_usec = static_cast<unsigned int>(t.tv_usec);
2349 // Since tv_usec never fills more than 11 bits we shift it to fill
2350 // in the slow-changing high-order bits of tv_sec.
2351 return tv_sec ^ (tv_usec << 21) ^ pid;
2355 //----------------------------------------------------------------------------
2356 static std::string cmSystemToolsExecutableDirectory;
2357 void cmSystemTools::FindExecutableDirectory(const char* argv0)
2359 #if defined(_WIN32) && !defined(__CYGWIN__)
2360 (void)argv0; // ignore this on windows
2361 char modulepath[_MAX_PATH];
2362 ::GetModuleFileName(NULL, modulepath, sizeof(modulepath));
2363 cmSystemToolsExecutableDirectory =
2364 cmSystemTools::GetFilenamePath(modulepath);
2367 std::string errorMsg;
2369 if(cmSystemTools::FindProgramPath(argv0, exe, errorMsg))
2372 exe = cmSystemTools::GetRealPath(exe.c_str());
2373 cmSystemToolsExecutableDirectory =
2374 cmSystemTools::GetFilenamePath(exe.c_str());
2383 //----------------------------------------------------------------------------
2384 const char* cmSystemTools::GetExecutableDirectory()
2386 return cmSystemToolsExecutableDirectory.c_str();
2389 //----------------------------------------------------------------------------
2390 #if defined(CMAKE_BUILD_WITH_CMAKE)
2391 void cmSystemTools::MakefileColorEcho(int color, const char* message,
2392 bool newline, bool enabled)
2394 // On some platforms (an MSYS prompt) cmsysTerminal may not be able
2395 // to determine whether the stream is displayed on a tty. In this
2396 // case it assumes no unless we tell it otherwise. Since we want
2397 // color messages to be displayed for users we will assume yes.
2398 // However, we can test for some situations when the answer is most
2400 int assumeTTY = cmsysTerminal_Color_AssumeTTY;
2401 if(cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
2402 cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
2403 cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE"))
2405 // Avoid printing color escapes during dashboard builds.
2411 cmsysTerminal_cfprintf(color | assumeTTY, stdout, "%s%s",
2412 message, newline? "\n" : "");
2416 // Color is disabled. Print without color.
2417 fprintf(stdout, "%s%s", message, newline? "\n" : "");
2422 //----------------------------------------------------------------------------
2423 bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
2424 std::string& soname)
2426 // For ELF shared libraries use a real parser to get the correct
2428 #if defined(CMAKE_USE_ELF_PARSER)
2429 cmELF elf(fullPath.c_str());
2432 return elf.GetSOName(soname);
2436 // If the file is not a symlink we have no guess for its soname.
2437 if(!cmSystemTools::FileIsSymlink(fullPath.c_str()))
2441 if(!cmSystemTools::ReadSymlink(fullPath.c_str(), soname))
2446 // If the symlink has a path component we have no guess for the soname.
2447 if(!cmSystemTools::GetFilenamePath(soname).empty())
2452 // If the symlink points at an extended version of the same name
2453 // assume it is the soname.
2454 std::string name = cmSystemTools::GetFilenameName(fullPath);
2455 if(soname.length() > name.length() &&
2456 soname.substr(0, name.length()) == name)
2463 //----------------------------------------------------------------------------
2464 bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
2465 std::string& soname)
2467 std::vector<cmStdString> cmds;
2468 cmds.push_back("otool");
2469 cmds.push_back("-D");
2470 cmds.push_back(fullPath.c_str());
2473 if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
2475 cmds.insert(cmds.begin(), "-r");
2476 cmds.insert(cmds.begin(), "xcrun");
2477 if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
2483 std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n");
2484 // otool returns extra lines reporting multiple install names
2485 // in case the binary is multi-arch and none of the architectures
2486 // is native (e.g. i386;ppc on x86_64)
2487 if(strs.size() >= 2)
2495 //----------------------------------------------------------------------------
2496 #if defined(CMAKE_USE_ELF_PARSER)
2497 std::string::size_type cmSystemToolsFindRPath(std::string const& have,
2498 std::string const& want)
2500 // Search for the desired rpath.
2501 std::string::size_type pos = have.find(want);
2503 // If the path is not present we are done.
2504 if(pos == std::string::npos)
2509 // Build a regex to match a properly separated path instance.
2510 std::string regex_str = "(^|:)(";
2511 for(std::string::const_iterator i = want.begin(); i != want.end(); ++i)
2514 if(!(('a' <= ch && ch <= 'z') ||
2515 ('A' <= ch && ch <= 'Z') ||
2516 ('0' <= ch && ch <= '9')))
2518 // Escape the non-alphanumeric character.
2521 // Store the character.
2522 regex_str.append(1, static_cast<char>(ch));
2524 regex_str += ")(:|$)";
2526 // Look for the separated path.
2527 cmsys::RegularExpression regex(regex_str.c_str());
2528 if(regex.find(have))
2530 // Return the position of the path portion.
2531 return regex.start(2);
2535 // The desired rpath was not found.
2536 return std::string::npos;
2541 #if defined(CMAKE_USE_ELF_PARSER)
2542 struct cmSystemToolsRPathInfo
2544 unsigned long Position;
2551 //----------------------------------------------------------------------------
2552 bool cmSystemTools::ChangeRPath(std::string const& file,
2553 std::string const& oldRPath,
2554 std::string const& newRPath,
2558 #if defined(CMAKE_USE_ELF_PARSER)
2564 cmSystemToolsRPathInfo rp[2];
2566 // Parse the ELF binary.
2567 cmELF elf(file.c_str());
2569 // Get the RPATH and RUNPATH entries from it.
2571 cmELF::StringEntry const* se[2] = {0, 0};
2572 const char* se_name[2] = {0, 0};
2573 if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2575 se[se_count] = se_rpath;
2576 se_name[se_count] = "RPATH";
2579 if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2581 se[se_count] = se_runpath;
2582 se_name[se_count] = "RUNPATH";
2587 if(newRPath.empty())
2589 // The new rpath is empty and there is no rpath anyway so it is
2597 *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
2598 *emsg += elf.GetErrorMessage();
2604 for(int i=0; i < se_count; ++i)
2606 // If both RPATH and RUNPATH refer to the same string literal it
2607 // needs to be changed only once.
2608 if(rp_count && rp[0].Position == se[i]->Position)
2613 // Make sure the current rpath contains the old rpath.
2614 std::string::size_type pos =
2615 cmSystemToolsFindRPath(se[i]->Value, oldRPath);
2616 if(pos == std::string::npos)
2618 // If it contains the new rpath instead then it is okay.
2619 if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
2626 e << "The current " << se_name[i] << " is:\n"
2627 << " " << se[i]->Value << "\n"
2628 << "which does not contain:\n"
2629 << " " << oldRPath << "\n"
2630 << "as was expected.";
2636 // Store information about the entry in the file.
2637 rp[rp_count].Position = se[i]->Position;
2638 rp[rp_count].Size = se[i]->Size;
2639 rp[rp_count].Name = se_name[i];
2641 // Construct the new value which preserves the part of the path
2642 // not being changed.
2643 rp[rp_count].Value = se[i]->Value.substr(0, pos);
2644 rp[rp_count].Value += newRPath;
2645 rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
2648 // Make sure there is enough room to store the new rpath and at
2649 // least one null terminator.
2650 if(rp[rp_count].Size < rp[rp_count].Value.length()+1)
2654 *emsg = "The replacement path is too long for the ";
2655 *emsg += se_name[i];
2661 // This entry is ready for update.
2666 // If no runtime path needs to be changed, we are done.
2673 // Open the file for update.
2674 std::ofstream f(file.c_str(),
2675 std::ios::in | std::ios::out | std::ios::binary);
2680 *emsg = "Error opening file for update.";
2685 // Store the new RPATH and RUNPATH strings.
2686 for(int i=0; i < rp_count; ++i)
2688 // Seek to the RPATH position.
2689 if(!f.seekp(rp[i].Position))
2693 *emsg = "Error seeking to ";
2694 *emsg += rp[i].Name;
2695 *emsg += " position.";
2700 // Write the new rpath. Follow it with enough null terminators to
2701 // fill the string table entry.
2703 for(unsigned long j=rp[i].Value.length(); j < rp[i].Size; ++j)
2708 // Make sure it wrote correctly.
2713 *emsg = "Error writing the new ";
2714 *emsg += rp[i].Name;
2715 *emsg += " string to the file.";
2722 // Everything was updated successfully.
2738 //----------------------------------------------------------------------------
2739 bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
2740 const char* lhss, const char* rhss)
2742 // Parse out up to 8 components.
2743 unsigned int lhs[8] = {0,0,0,0,0,0,0,0};
2744 unsigned int rhs[8] = {0,0,0,0,0,0,0,0};
2745 sscanf(lhss, "%u.%u.%u.%u.%u.%u.%u.%u",
2746 &lhs[0], &lhs[1], &lhs[2], &lhs[3],
2747 &lhs[4], &lhs[5], &lhs[6], &lhs[7]);
2748 sscanf(rhss, "%u.%u.%u.%u.%u.%u.%u.%u",
2749 &rhs[0], &rhs[1], &rhs[2], &rhs[3],
2750 &rhs[4], &rhs[5], &rhs[6], &rhs[7]);
2752 // Do component-wise comparison.
2753 for(unsigned int i=0; i < 8; ++i)
2757 // lhs < rhs, so true if operation is LESS
2758 return op == cmSystemTools::OP_LESS;
2760 else if(lhs[i] > rhs[i])
2762 // lhs > rhs, so true if operation is GREATER
2763 return op == cmSystemTools::OP_GREATER;
2766 // lhs == rhs, so true if operation is EQUAL
2767 return op == cmSystemTools::OP_EQUAL;
2770 //----------------------------------------------------------------------------
2771 bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
2774 #if defined(CMAKE_USE_ELF_PARSER)
2780 unsigned long zeroPosition[2] = {0,0};
2781 unsigned long zeroSize[2] = {0,0};
2782 unsigned long bytesBegin = 0;
2783 std::vector<char> bytes;
2785 // Parse the ELF binary.
2786 cmELF elf(file.c_str());
2788 // Get the RPATH and RUNPATH entries from it and sort them by index
2789 // in the dynamic section header.
2791 cmELF::StringEntry const* se[2] = {0, 0};
2792 if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2794 se[se_count++] = se_rpath;
2796 if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2798 se[se_count++] = se_runpath;
2802 // There is no RPATH or RUNPATH anyway.
2805 if(se_count == 2 && se[1]->IndexInSection < se[0]->IndexInSection)
2807 cmsys_stl::swap(se[0], se[1]);
2810 // Get the size of the dynamic section header.
2811 unsigned int count = elf.GetDynamicEntryCount();
2814 // This should happen only for invalid ELF files where a DT_NULL
2815 // appears before the end of the table.
2818 *emsg = "DYNAMIC section contains a DT_NULL before the end.";
2823 // Save information about the string entries to be zeroed.
2824 zeroCount = se_count;
2825 for(int i=0; i < se_count; ++i)
2827 zeroPosition[i] = se[i]->Position;
2828 zeroSize[i] = se[i]->Size;
2831 // Get the range of file positions corresponding to each entry and
2832 // the rest of the table after them.
2833 unsigned long entryBegin[3] = {0,0,0};
2834 unsigned long entryEnd[2] = {0,0};
2835 for(int i=0; i < se_count; ++i)
2837 entryBegin[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection);
2838 entryEnd[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection+1);
2840 entryBegin[se_count] = elf.GetDynamicEntryPosition(count);
2842 // The data are to be written over the old table entries starting at
2843 // the first one being removed.
2844 bytesBegin = entryBegin[0];
2845 unsigned long bytesEnd = entryBegin[se_count];
2847 // Allocate a buffer to hold the part of the file to be written.
2848 // Initialize it with zeros.
2849 bytes.resize(bytesEnd - bytesBegin, 0);
2851 // Read the part of the DYNAMIC section header that will move.
2852 // The remainder of the buffer will be left with zeros which
2853 // represent a DT_NULL entry.
2854 char* data = &bytes[0];
2855 for(int i=0; i < se_count; ++i)
2857 // Read data between the entries being removed.
2858 unsigned long sz = entryBegin[i+1] - entryEnd[i];
2859 if(sz > 0 && !elf.ReadBytes(entryEnd[i], sz, data))
2863 *emsg = "Failed to read DYNAMIC section header.";
2871 // Open the file for update.
2872 std::ofstream f(file.c_str(),
2873 std::ios::in | std::ios::out | std::ios::binary);
2878 *emsg = "Error opening file for update.";
2883 // Write the new DYNAMIC table header.
2884 if(!f.seekp(bytesBegin))
2888 *emsg = "Error seeking to DYNAMIC table header for RPATH.";
2892 if(!f.write(&bytes[0], bytes.size()))
2896 *emsg = "Error replacing DYNAMIC table header.";
2901 // Fill the RPATH and RUNPATH strings with zero bytes.
2902 for(int i=0; i < zeroCount; ++i)
2904 if(!f.seekp(zeroPosition[i]))
2908 *emsg = "Error seeking to RPATH position.";
2912 for(unsigned long j=0; j < zeroSize[i]; ++j)
2920 *emsg = "Error writing the empty rpath string to the file.";
2926 // Everything was updated successfully.
2940 //----------------------------------------------------------------------------
2941 bool cmSystemTools::CheckRPath(std::string const& file,
2942 std::string const& newRPath)
2944 #if defined(CMAKE_USE_ELF_PARSER)
2945 // Parse the ELF binary.
2946 cmELF elf(file.c_str());
2948 // Get the RPATH or RUNPATH entry from it.
2949 cmELF::StringEntry const* se = elf.GetRPath();
2952 se = elf.GetRunPath();
2955 // Make sure the current rpath contains the new rpath.
2956 if(newRPath.empty())
2966 cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
2979 //----------------------------------------------------------------------------
2980 bool cmSystemTools::RepeatedRemoveDirectory(const char* dir)
2982 // Windows sometimes locks files temporarily so try a few times.
2983 for(int i = 0; i < 10; ++i)
2985 if(cmSystemTools::RemoveADirectory(dir))
2989 cmSystemTools::Delay(100);
2994 //----------------------------------------------------------------------------
2995 std::vector<std::string> cmSystemTools::tokenize(const std::string& str,
2996 const std::string& sep)
2998 std::vector<std::string> tokens;
2999 std::string::size_type tokend = 0;
3003 std::string::size_type tokstart=str.find_first_not_of(sep, tokend);
3004 if (tokstart==std::string::npos)
3006 break; // no more tokens
3008 tokend=str.find_first_of(sep,tokstart);
3009 if (tokend==std::string::npos)
3011 tokens.push_back(str.substr(tokstart));
3015 tokens.push_back(str.substr(tokstart,tokend-tokstart));
3017 } while (tokend!=std::string::npos);
3021 tokens.push_back("");