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)
55 # include <memory> // auto_ptr
57 # include "cmCryptoHash.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_; }
107 #elif defined(__APPLE__)
108 #include <crt_externs.h>
109 #define environ (*_NSGetEnviron())
112 bool cmSystemTools::s_RunCommandHideConsole = false;
113 bool cmSystemTools::s_DisableRunCommandOutput = false;
114 bool cmSystemTools::s_ErrorOccured = false;
115 bool cmSystemTools::s_FatalErrorOccured = false;
116 bool cmSystemTools::s_DisableMessages = false;
117 bool cmSystemTools::s_ForceUnixPaths = false;
119 std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com";
120 void cmSystemTools::SetWindows9xComspecSubstitute(const char* str)
124 cmSystemTools::s_Windows9xComspecSubstitute = str;
127 const char* cmSystemTools::GetWindows9xComspecSubstitute()
129 return cmSystemTools::s_Windows9xComspecSubstitute.c_str();
132 void (*cmSystemTools::s_ErrorCallback)(const char*, const char*,
134 void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*);
135 void* cmSystemTools::s_ErrorCallbackClientData = 0;
136 void* cmSystemTools::s_StdoutCallbackClientData = 0;
137 bool (*cmSystemTools::s_InterruptCallback)(void*);
138 void* cmSystemTools::s_InterruptCallbackClientData = 0;
140 // replace replace with with as many times as it shows up in source.
141 // write the result into source.
142 #if defined(_WIN32) && !defined(__CYGWIN__)
143 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view)
145 // Regular expression to match anything inside [...] that begins in HKEY.
146 // Note that there is a special rule for regular expressions to match a
147 // close square-bracket inside a list delimited by square brackets.
148 // The "[^]]" part of this expression will match any character except
149 // a close square-bracket. The ']' character must be the first in the
150 // list of characters inside the [^...] block of the expression.
151 cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
153 // check for black line or comment
154 while (regEntry.find(source))
156 // the arguments are the second match
157 std::string key = regEntry.match(1);
159 if (ReadRegistryValue(key.c_str(), val, view))
161 std::string reg = "[";
163 cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
167 std::string reg = "[";
169 cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
174 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64)
176 cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
177 while (regEntry.find(source))
179 // the arguments are the second match
180 std::string key = regEntry.match(1);
182 std::string reg = "[";
184 cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
190 std::string cmSystemTools::EscapeQuotes(const char* str)
192 std::string result = "";
193 for(const char* ch = str; *ch != '\0'; ++ch)
204 std::string cmSystemTools::TrimWhitespace(const std::string& s)
206 std::string::const_iterator start = s.begin();
207 while(start != s.end() && *start == ' ')
209 if (start == s.end())
212 std::string::const_iterator stop = s.end()-1;
215 return std::string(start, stop+1);
218 void cmSystemTools::Error(const char* m1, const char* m2,
219 const char* m3, const char* m4)
221 std::string message = "CMake Error: ";
238 cmSystemTools::s_ErrorOccured = true;
239 cmSystemTools::Message(message.c_str(),"Error");
242 void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData)
244 s_InterruptCallback = f;
245 s_InterruptCallbackClientData = clientData;
248 bool cmSystemTools::GetInterruptFlag()
250 if(s_InterruptCallback)
252 return (*s_InterruptCallback)(s_InterruptCallbackClientData);
257 void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData)
260 s_ErrorCallbackClientData = clientData;
263 void cmSystemTools::SetStdoutCallback(StdoutCallback f, void* clientData)
265 s_StdoutCallback = f;
266 s_StdoutCallbackClientData = clientData;
269 void cmSystemTools::Stdout(const char* s)
273 (*s_StdoutCallback)(s, static_cast<int>(strlen(s)),
274 s_StdoutCallbackClientData);
283 void cmSystemTools::Stderr(const char* s, int length)
285 std::cerr.write(s, length);
289 void cmSystemTools::Stdout(const char* s, int length)
293 (*s_StdoutCallback)(s, length, s_StdoutCallbackClientData);
297 std::cout.write(s, length);
302 void cmSystemTools::Message(const char* m1, const char *title)
304 if(s_DisableMessages)
310 (*s_ErrorCallback)(m1, title, s_DisableMessages,
311 s_ErrorCallbackClientData);
316 std::cerr << m1 << std::endl << std::flush;
322 void cmSystemTools::ReportLastSystemError(const char* msg)
325 m += ": System Error: ";
326 m += Superclass::GetLastSystemError();
327 cmSystemTools::Error(m.c_str());
330 bool cmSystemTools::IsInternallyOn(const char* val)
336 std::basic_string<char> v = val;
338 for(std::basic_string<char>::iterator c = v.begin();
341 *c = static_cast<char>(toupper(*c));
343 return (v == "I_ON" || v == "i_on");
346 bool cmSystemTools::IsOn(const char* val)
352 std::basic_string<char> v = val;
354 for(std::basic_string<char>::iterator c = v.begin();
357 *c = static_cast<char>(toupper(*c));
359 return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y");
362 bool cmSystemTools::IsNOTFOUND(const char* val)
364 size_t len = strlen(val);
365 const char* notfound = "-NOTFOUND";
366 const size_t lenNotFound = 9;
367 if(len < lenNotFound-1)
371 if(len == lenNotFound-1)
373 return ( strcmp(val, "NOTFOUND") == 0);
375 return ((strncmp((val + (len - lenNotFound)), notfound, lenNotFound) == 0));
379 bool cmSystemTools::IsOff(const char* val)
381 if (!val || strlen(val) == 0)
385 std::basic_string<char> v = val;
387 for(std::basic_string<char>::iterator c = v.begin();
390 *c = static_cast<char>(toupper(*c));
392 return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" ||
393 v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE");
396 //----------------------------------------------------------------------------
397 void cmSystemTools::ParseWindowsCommandLine(const char* command,
398 std::vector<std::string>& args)
400 // See the MSDN document "Parsing C Command-Line Arguments" at
401 // http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx for rules
402 // of parsing the windows command line.
404 bool in_argument = false;
405 bool in_quotes = false;
408 for(const char* c = command;*c; ++c)
417 int backslash_pairs = backslashes >> 1;
418 int backslash_escaped = backslashes & 1;
419 arg.append(backslash_pairs, '\\');
421 if(backslash_escaped)
423 /* An odd number of backslashes precede this quote.
429 /* An even number of backslashes precede this quote.
430 It is not escaped. */
431 in_quotes = !in_quotes;
437 arg.append(backslashes, '\\');
459 arg.append(backslashes, '\\');
466 //----------------------------------------------------------------------------
467 class cmSystemToolsArgV
471 cmSystemToolsArgV(char** argv): ArgV(argv) {}
474 for(char** arg = this->ArgV; arg && *arg; ++arg)
480 void Store(std::vector<std::string>& args) const
482 for(char** arg = this->ArgV; arg && *arg; ++arg)
484 args.push_back(*arg);
487 void Store(std::vector<cmStdString>& args) const
489 for(char** arg = this->ArgV; arg && *arg; ++arg)
491 args.push_back(*arg);
496 //----------------------------------------------------------------------------
497 void cmSystemTools::ParseUnixCommandLine(const char* command,
498 std::vector<std::string>& args)
500 // Invoke the underlying parser.
501 cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
505 //----------------------------------------------------------------------------
506 void cmSystemTools::ParseUnixCommandLine(const char* command,
507 std::vector<cmStdString>& args)
509 // Invoke the underlying parser.
510 cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
514 std::string cmSystemTools::EscapeWindowsShellArgument(const char* arg,
517 char local_buffer[1024];
518 char* buffer = local_buffer;
519 int size = cmsysSystem_Shell_GetArgumentSizeForWindows(arg, shell_flags);
522 buffer = new char[size];
524 cmsysSystem_Shell_GetArgumentForWindows(arg, buffer, shell_flags);
525 std::string result(buffer);
526 if(buffer != local_buffer)
533 std::vector<cmStdString> cmSystemTools::ParseArguments(const char* command)
535 std::vector<cmStdString> args;
538 bool win_path = false;
540 if ((command[0] != '/' && command[1] == ':' && command[2] == '\\') ||
541 (command[0] == '\"' && command[1] != '/' && command[2] == ':'
542 && command[3] == '\\') ||
543 (command[0] == '\'' && command[1] != '/' && command[2] == ':'
544 && command[3] == '\\') ||
545 (command[0] == '\\' && command[1] == '\\'))
549 // Split the command into an argv array.
550 for(const char* c = command; *c;)
552 // Skip over whitespace.
553 while(*c == ' ' || *c == '\t')
560 // Parse a quoted argument.
562 while(*c && *c != '"')
575 // Parse a quoted argument.
577 while(*c && *c != '\'')
590 // Parse an unquoted argument.
591 while(*c && *c != ' ' && *c != '\t')
593 if(*c == '\\' && !win_path)
616 bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
617 std::string* output ,
618 int* retVal , const char* dir ,
619 OutputOption outputflag ,
622 std::vector<const char*> argv;
623 for(std::vector<cmStdString>::const_iterator a = command.begin();
624 a != command.end(); ++a)
626 argv.push_back(a->c_str());
634 cmsysProcess* cp = cmsysProcess_New();
635 cmsysProcess_SetCommand(cp, &*argv.begin());
636 cmsysProcess_SetWorkingDirectory(cp, dir);
637 if(cmSystemTools::GetRunCommandHideConsole())
639 cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
642 cmsysProcess_SetTimeout(cp, timeout);
643 cmsysProcess_Execute(cp);
645 std::vector<char> tempOutput;
649 if ( output || outputflag != OUTPUT_NONE )
651 while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0)
653 if(output || outputflag != OUTPUT_NONE)
655 // Translate NULL characters in the output into valid text.
656 // Visual Studio 7 puts these characters in the output of its
658 for(int i=0; i < length; ++i)
668 tempOutput.insert(tempOutput.end(), data, data+length);
670 if(outputflag != OUTPUT_NONE)
672 if(outputflag == OUTPUT_MERGE)
674 cmSystemTools::Stdout(data, length);
678 if(pipe == cmsysProcess_Pipe_STDERR)
680 cmSystemTools::Stderr(data, length);
682 else if(pipe == cmsysProcess_Pipe_STDOUT)
684 cmSystemTools::Stdout(data, length);
691 cmsysProcess_WaitForExit(cp, 0);
692 if ( output && tempOutput.begin() != tempOutput.end())
694 output->append(&*tempOutput.begin(), tempOutput.size());
698 if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
702 *retVal = cmsysProcess_GetExitValue(cp);
706 if ( cmsysProcess_GetExitValue(cp) != 0 )
712 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
714 const char* exception_str = cmsysProcess_GetExceptionString(cp);
715 if ( outputflag != OUTPUT_NONE )
717 std::cerr << exception_str << std::endl;
721 output->append(exception_str, strlen(exception_str));
725 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
727 const char* error_str = cmsysProcess_GetErrorString(cp);
728 if ( outputflag != OUTPUT_NONE )
730 std::cerr << error_str << std::endl;
734 output->append(error_str, strlen(error_str));
738 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
740 const char* error_str = "Process terminated due to timeout\n";
741 if ( outputflag != OUTPUT_NONE )
743 std::cerr << error_str << std::endl;
747 output->append(error_str, strlen(error_str));
752 cmsysProcess_Delete(cp);
756 bool cmSystemTools::RunSingleCommand(
761 OutputOption outputflag,
764 if(s_DisableRunCommandOutput)
766 outputflag = OUTPUT_NONE;
769 std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
775 return cmSystemTools::RunSingleCommand(args, output,retVal,
776 dir, outputflag, timeout);
778 bool cmSystemTools::RunCommand(const char* command,
785 return cmSystemTools::RunCommand(command, output, dummy,
786 dir, verbose, timeout);
789 #if defined(WIN32) && !defined(__CYGWIN__)
790 #include "cmWin32ProcessExecution.h"
791 // use this for shell commands like echo and dir
792 bool RunCommandViaWin32(const char* command,
799 #if defined(__BORLANDC__)
801 cmWin32ProcessExecution::
802 BorlandRunCommand(command, dir, output,
805 cmSystemTools::GetRunCommandHideConsole());
806 #else // Visual studio
807 ::SetLastError(ERROR_SUCCESS);
810 cmSystemTools::Error("No command specified");
813 cmWin32ProcessExecution resProc;
814 if(cmSystemTools::GetRunCommandHideConsole())
816 resProc.SetHideWindows(true);
819 if ( cmSystemTools::GetWindows9xComspecSubstitute() )
821 resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
823 if ( !resProc.StartProcess(command, dir, verbose) )
825 output = resProc.GetOutput();
828 cmSystemTools::Stdout(output.c_str());
832 resProc.Wait(timeout);
833 output = resProc.GetOutput();
834 retVal = resProc.GetExitValue();
839 // use this for shell commands like echo and dir
840 bool RunCommandViaSystem(const char* command,
846 std::cout << "@@ " << command << std::endl;
848 std::string commandInDir;
851 commandInDir = "cd ";
852 commandInDir += cmSystemTools::ConvertToOutputPath(dir);
853 commandInDir += " && ";
854 commandInDir += command;
858 commandInDir = command;
860 command = commandInDir.c_str();
861 std::string commandToFile = command;
862 commandToFile += " > ";
863 std::string tempFile;
864 tempFile += _tempnam(0, "cmake");
866 commandToFile += tempFile;
867 retVal = system(commandToFile.c_str());
868 std::ifstream fin(tempFile.c_str());
873 std::string errormsg = "RunCommand produced no output: command: \"";
876 errormsg += "\nOutput file: ";
877 errormsg += tempFile;
878 cmSystemTools::Error(errormsg.c_str());
881 cmSystemTools::RemoveFile(tempFile.c_str());
884 bool multiLine = false;
886 while(cmSystemTools::GetLineFromStream(fin, line))
896 cmSystemTools::RemoveFile(tempFile.c_str());
900 #else // We have popen
902 // BeOS seems to return from a successful pclose() before the process has
903 // legitimately exited, or at least before SIGCHLD is thrown...the signal may
904 // come quite some time after pclose returns! This causes havoc with later
905 // parts of CMake that expect to catch the signal from other child processes,
906 // so we explicitly wait to catch it here. This should be safe to do with
907 // popen() so long as we don't actually collect the zombie process ourselves.
910 #undef SIGBUS // this is the same as SIGSEGV on BeOS and causes issues below.
911 static volatile bool beos_seen_signal = false;
912 static void beos_popen_workaround(int sig)
914 beos_seen_signal = true;
918 bool RunCommandViaPopen(const char* command,
925 // if only popen worked on windows.....
926 std::string commandInDir;
929 commandInDir = "cd \"";
931 commandInDir += "\" && ";
932 commandInDir += command;
936 commandInDir = command;
939 commandInDir += " 2>&1";
941 command = commandInDir.c_str();
942 const int BUFFER_SIZE = 4096;
943 char buffer[BUFFER_SIZE];
946 cmSystemTools::Stdout("running ");
947 cmSystemTools::Stdout(command);
948 cmSystemTools::Stdout("\n");
954 beos_seen_signal = false;
955 signal(SIGCHLD, beos_popen_workaround);
958 FILE* cpipe = popen(command, "r");
962 signal(SIGCHLD, SIG_DFL);
966 if (!fgets(buffer, BUFFER_SIZE, cpipe))
974 cmSystemTools::Stdout(buffer);
977 if(!fgets(buffer, BUFFER_SIZE, cpipe))
983 retVal = pclose(cpipe);
986 for (int i = 0; (!beos_seen_signal) && (i < 3); i++)
988 ::sleep(1); // signals should interrupt this...
991 if (!beos_seen_signal)
993 signal(SIGCHLD, SIG_DFL); // oh well, didn't happen. Go on anyhow.
997 if (WIFEXITED(retVal))
999 retVal = WEXITSTATUS(retVal);
1002 if (WIFSIGNALED(retVal))
1004 retVal = WTERMSIG(retVal);
1005 cmOStringStream error;
1006 error << "\nProcess terminated due to ";
1032 error << "signal " << retVal;
1035 output += error.str();
1040 #endif // endif WIN32 not CYGWIN
1043 // run a command unix uses popen (easy)
1044 // windows uses system and ShortPath
1045 bool cmSystemTools::RunCommand(const char* command,
1046 std::string& output,
1052 if(s_DisableRunCommandOutput)
1057 #if defined(WIN32) && !defined(__CYGWIN__)
1058 // if the command does not start with a quote, then
1059 // try to find the program, and if the program can not be
1060 // found use system to run the command as it must be a built in
1061 // shell command like echo or dir
1063 if(command[0] == '\"')
1065 // count the number of quotes
1066 for(const char* s = command; *s != 0; ++s)
1077 // if there are more than two double quotes use
1078 // GetShortPathName, the cmd.exe program in windows which
1079 // is used by system fails to execute if there are more than
1080 // one set of quotes in the arguments
1083 cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
1084 if(quoted.find(command))
1086 std::string shortCmd;
1087 std::string cmd = quoted.match(1);
1088 std::string args = quoted.match(2);
1089 if(! cmSystemTools::FileExists(cmd.c_str()) )
1093 else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd))
1095 cmSystemTools::Error("GetShortPath failed for " , cmd.c_str());
1101 //return RunCommandViaSystem(shortCmd.c_str(), dir,
1102 // output, retVal, verbose);
1103 //return WindowsRunCommand(shortCmd.c_str(), dir,
1104 //output, retVal, verbose);
1105 return RunCommandViaWin32(shortCmd.c_str(), dir,
1106 output, retVal, verbose, timeout);
1110 cmSystemTools::Error("Could not parse command line with quotes ",
1115 // if there is only one set of quotes or no quotes then just run the command
1116 //return RunCommandViaSystem(command, dir, output, retVal, verbose);
1117 //return WindowsRunCommand(command, dir, output, retVal, verbose);
1118 return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout);
1120 return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout);
1124 bool cmSystemTools::DoesFileExistWithExtensions(
1126 const std::vector<std::string>& headerExts)
1130 for( std::vector<std::string>::const_iterator ext = headerExts.begin();
1131 ext != headerExts.end(); ++ext )
1136 if(cmSystemTools::FileExists(hname.c_str()))
1144 std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
1145 const char* directory, const char* toplevel)
1147 std::string file = fname;
1148 cmSystemTools::ConvertToUnixSlashes(file);
1149 std::string dir = directory;
1150 cmSystemTools::ConvertToUnixSlashes(dir);
1151 std::string prevDir;
1152 while(dir != prevDir)
1154 std::string path = dir + "/" + file;
1155 if ( cmSystemTools::FileExists(path.c_str()) )
1159 if ( dir.size() < strlen(toplevel) )
1164 dir = cmSystemTools::GetParentDirectory(dir.c_str());
1169 bool cmSystemTools::cmCopyFile(const char* source, const char* destination)
1171 return Superclass::CopyFileAlways(source, destination);
1174 bool cmSystemTools::CopyFileIfDifferent(const char* source,
1175 const char* destination)
1177 return Superclass::CopyFileIfDifferent(source, destination);
1180 //----------------------------------------------------------------------------
1181 bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
1184 /* On Windows the move functions will not replace existing files.
1185 Check if the destination exists. */
1186 struct stat newFile;
1187 if(stat(newname, &newFile) == 0)
1189 /* The destination exists. We have to replace it carefully. The
1190 MoveFileEx function does what we need but is not available on
1195 /* Make sure the destination is not read only. */
1196 attrs = GetFileAttributes(newname);
1197 if(attrs & FILE_ATTRIBUTE_READONLY)
1199 SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
1202 /* Check the windows version number. */
1203 osv.dwOSVersionInfoSize = sizeof(osv);
1205 if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
1207 /* This is Win9x. There is no MoveFileEx implementation. We
1208 cannot quite rename the file atomically. Just delete the
1209 destination and then move the file. */
1210 DeleteFile(newname);
1211 return MoveFile(oldname, newname) != 0;
1215 /* This is not Win9x. Use the MoveFileEx implementation. */
1216 return MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) != 0;
1221 /* The destination does not exist. Just move the file. */
1222 return MoveFile(oldname, newname) != 0;
1225 /* On UNIX we have an OS-provided call to do this atomically. */
1226 return rename(oldname, newname) == 0;
1230 bool cmSystemTools::ComputeFileMD5(const char* source, char* md5out)
1232 #if defined(CMAKE_BUILD_WITH_CMAKE)
1233 cmCryptoHashMD5 md5;
1234 std::string str = md5.HashFile(source);
1235 strncpy(md5out, str.c_str(), 32);
1236 return !str.empty();
1240 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1245 std::string cmSystemTools::ComputeStringMD5(const char* input)
1247 #if defined(CMAKE_BUILD_WITH_CMAKE)
1248 cmCryptoHashMD5 md5;
1249 return md5.HashString(input);
1252 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1257 void cmSystemTools::Glob(const char *directory, const char *regexp,
1258 std::vector<std::string>& files)
1261 cmsys::RegularExpression reg(regexp);
1263 if (d.Load(directory))
1267 numf = d.GetNumberOfFiles();
1268 for (i = 0; i < numf; i++)
1270 std::string fname = d.GetFile(i);
1271 if (reg.find(fname))
1273 files.push_back(fname);
1280 void cmSystemTools::GlobDirs(const char *fullPath,
1281 std::vector<std::string>& files)
1283 std::string path = fullPath;
1284 std::string::size_type pos = path.find("/*");
1285 if(pos == std::string::npos)
1287 files.push_back(fullPath);
1290 std::string startPath = path.substr(0, pos);
1291 std::string finishPath = path.substr(pos+2);
1294 if (d.Load(startPath.c_str()))
1296 for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
1298 if((std::string(d.GetFile(i)) != ".")
1299 && (std::string(d.GetFile(i)) != ".."))
1301 std::string fname = startPath;
1303 fname += d.GetFile(i);
1304 if(cmSystemTools::FileIsDirectory(fname.c_str()))
1306 fname += finishPath;
1307 cmSystemTools::GlobDirs(fname.c_str(), files);
1315 void cmSystemTools::ExpandList(std::vector<std::string> const& arguments,
1316 std::vector<std::string>& newargs)
1318 std::vector<std::string>::const_iterator i;
1319 for(i = arguments.begin();i != arguments.end(); ++i)
1321 cmSystemTools::ExpandListArgument(*i, newargs);
1325 void cmSystemTools::ExpandListArgument(const std::string& arg,
1326 std::vector<std::string>& newargs,
1329 // If argument is empty, it is an empty list.
1330 if(arg.length() == 0 && !emptyArgs)
1334 // if there are no ; in the name then just copy the current string
1335 if(arg.find(';') == std::string::npos)
1337 newargs.push_back(arg);
1340 std::vector<char> newArgVec;
1341 // Break the string at non-escaped semicolons not nested in [].
1342 int squareNesting = 0;
1343 for(const char* c = arg.c_str(); *c; ++c)
1349 // We only want to allow escaping of semicolons. Other
1350 // escapes should not be processed here.
1354 newArgVec.push_back(*c);
1358 newArgVec.push_back('\\');
1361 newArgVec.push_back(*c);
1365 // Terminate the loop properly.
1373 newArgVec.push_back(*c);
1378 newArgVec.push_back(*c);
1382 // Break the string here if we are not nested inside square
1384 if(squareNesting == 0)
1386 if ( newArgVec.size() || emptyArgs )
1388 // Add the last argument if the string is not empty.
1389 newArgVec.push_back(0);
1390 newargs.push_back(&*newArgVec.begin());
1396 newArgVec.push_back(*c);
1401 // Just append this character.
1402 newArgVec.push_back(*c);
1406 if ( newArgVec.size() || emptyArgs )
1408 // Add the last argument if the string is not empty.
1409 newArgVec.push_back(0);
1410 newargs.push_back(&*newArgVec.begin());
1414 bool cmSystemTools::SimpleGlob(const cmStdString& glob,
1415 std::vector<cmStdString>& files,
1419 if ( glob[glob.size()-1] != '*' )
1423 std::string path = cmSystemTools::GetFilenamePath(glob);
1424 std::string ppath = cmSystemTools::GetFilenameName(glob);
1425 ppath = ppath.substr(0, ppath.size()-1);
1426 if ( path.size() == 0 )
1433 if (d.Load(path.c_str()))
1435 for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
1437 if((std::string(d.GetFile(i)) != ".")
1438 && (std::string(d.GetFile(i)) != ".."))
1440 std::string fname = path;
1441 if ( path[path.size()-1] != '/' )
1445 fname += d.GetFile(i);
1446 std::string sfname = d.GetFile(i);
1447 if ( type > 0 && cmSystemTools::FileIsDirectory(fname.c_str()) )
1451 if ( type < 0 && !cmSystemTools::FileIsDirectory(fname.c_str()) )
1455 if ( sfname.size() >= ppath.size() &&
1456 sfname.substr(0, ppath.size()) ==
1459 files.push_back(fname);
1468 cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext)
1470 if ( ! cext || *cext == 0 )
1472 return cmSystemTools::NO_FILE_FORMAT;
1474 //std::string ext = cmSystemTools::LowerCase(cext);
1475 std::string ext = cext;
1476 if ( ext == "c" || ext == ".c" ||
1477 ext == "m" || ext == ".m"
1478 ) { return cmSystemTools::C_FILE_FORMAT; }
1480 ext == "C" || ext == ".C" ||
1481 ext == "M" || ext == ".M" ||
1482 ext == "c++" || ext == ".c++" ||
1483 ext == "cc" || ext == ".cc" ||
1484 ext == "cpp" || ext == ".cpp" ||
1485 ext == "cxx" || ext == ".cxx" ||
1486 ext == "mm" || ext == ".mm"
1487 ) { return cmSystemTools::CXX_FILE_FORMAT; }
1489 ext == "f" || ext == ".f" ||
1490 ext == "F" || ext == ".F" ||
1491 ext == "f77" || ext == ".f77" ||
1492 ext == "f90" || ext == ".f90" ||
1493 ext == "for" || ext == ".for" ||
1494 ext == "f95" || ext == ".f95"
1495 ) { return cmSystemTools::FORTRAN_FILE_FORMAT; }
1496 if ( ext == "java" || ext == ".java" )
1497 { return cmSystemTools::JAVA_FILE_FORMAT; }
1499 ext == "H" || ext == ".H" ||
1500 ext == "h" || ext == ".h" ||
1501 ext == "h++" || ext == ".h++" ||
1502 ext == "hm" || ext == ".hm" ||
1503 ext == "hpp" || ext == ".hpp" ||
1504 ext == "hxx" || ext == ".hxx" ||
1505 ext == "in" || ext == ".in" ||
1506 ext == "txx" || ext == ".txx"
1507 ) { return cmSystemTools::HEADER_FILE_FORMAT; }
1508 if ( ext == "rc" || ext == ".rc" )
1509 { return cmSystemTools::RESOURCE_FILE_FORMAT; }
1510 if ( ext == "def" || ext == ".def" )
1511 { return cmSystemTools::DEFINITION_FILE_FORMAT; }
1512 if ( ext == "lib" || ext == ".lib" ||
1513 ext == "a" || ext == ".a")
1514 { return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT; }
1515 if ( ext == "o" || ext == ".o" ||
1516 ext == "obj" || ext == ".obj")
1517 { return cmSystemTools::OBJECT_FILE_FORMAT; }
1519 if ( ext == "dylib" || ext == ".dylib" )
1520 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; }
1521 if ( ext == "so" || ext == ".so" ||
1522 ext == "bundle" || ext == ".bundle" )
1523 { return cmSystemTools::MODULE_FILE_FORMAT; }
1525 if ( ext == "so" || ext == ".so" ||
1526 ext == "sl" || ext == ".sl" ||
1527 ext == "dll" || ext == ".dll" )
1528 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; }
1530 return cmSystemTools::UNKNOWN_FILE_FORMAT;
1533 bool cmSystemTools::Split(const char* s, std::vector<cmStdString>& l)
1535 std::vector<std::string> temp;
1536 bool res = Superclass::Split(s, temp);
1537 for(std::vector<std::string>::const_iterator i = temp.begin();
1538 i != temp.end(); ++i)
1545 std::string cmSystemTools::ConvertToOutputPath(const char* path)
1547 #if defined(_WIN32) && !defined(__CYGWIN__)
1548 if(s_ForceUnixPaths)
1550 return cmSystemTools::ConvertToUnixOutputPath(path);
1552 return cmSystemTools::ConvertToWindowsOutputPath(path);
1554 return cmSystemTools::ConvertToUnixOutputPath(path);
1558 void cmSystemTools::ConvertToOutputSlashes(std::string& path)
1560 #if defined(_WIN32) && !defined(__CYGWIN__)
1561 if(!s_ForceUnixPaths)
1563 // Convert to windows slashes.
1564 std::string::size_type pos = 0;
1565 while((pos = path.find('/', pos)) != std::string::npos)
1571 static_cast<void>(path);
1575 std::string cmSystemTools::ConvertToRunCommandPath(const char* path)
1577 #if defined(_WIN32) && !defined(__CYGWIN__)
1578 return cmSystemTools::ConvertToWindowsOutputPath(path);
1580 return cmSystemTools::ConvertToUnixOutputPath(path);
1584 bool cmSystemTools::StringEndsWith(const char* str1, const char* str2)
1586 if ( !str1 || !str2 || strlen(str1) < strlen(str2) )
1590 return !strncmp(str1 + (strlen(str1)-strlen(str2)), str2, strlen(str2));
1593 // compute the relative path from here to there
1594 std::string cmSystemTools::RelativePath(const char* local, const char* remote)
1596 if(!cmSystemTools::FileIsFullPath(local))
1598 cmSystemTools::Error("RelativePath must be passed a full path to local: ",
1601 if(!cmSystemTools::FileIsFullPath(remote))
1603 cmSystemTools::Error
1604 ("RelativePath must be passed a full path to remote: ", remote);
1606 return cmsys::SystemTools::RelativePath(local, remote);
1609 #ifdef CMAKE_BUILD_WITH_CMAKE
1610 //----------------------------------------------------------------------
1611 bool cmSystemTools::UnsetEnv(const char* value)
1613 #if !defined(HAVE_UNSETENV)
1614 std::string var = value;
1616 return cmSystemTools::PutEnv(var.c_str());
1623 //----------------------------------------------------------------------
1624 std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
1626 std::vector<std::string> env;
1628 for ( cc = 0; environ[cc]; ++ cc )
1630 env.push_back(environ[cc]);
1635 //----------------------------------------------------------------------
1636 void cmSystemTools::AppendEnv(std::vector<std::string> const& env)
1638 for(std::vector<std::string>::const_iterator eit = env.begin();
1639 eit != env.end(); ++eit)
1641 cmSystemTools::PutEnv(eit->c_str());
1645 //----------------------------------------------------------------------
1646 cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
1648 this->Env = cmSystemTools::GetEnvironmentVariables();
1651 //----------------------------------------------------------------------
1652 cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
1654 // First clear everything in the current environment:
1655 std::vector<std::string> currentEnv = GetEnvironmentVariables();
1656 for(std::vector<std::string>::const_iterator
1657 eit = currentEnv.begin(); eit != currentEnv.end(); ++eit)
1659 std::string var(*eit);
1661 std::string::size_type pos = var.find("=");
1662 if (pos != std::string::npos)
1664 var = var.substr(0, pos);
1667 cmSystemTools::UnsetEnv(var.c_str());
1670 // Then put back each entry from the original environment:
1671 cmSystemTools::AppendEnv(this->Env);
1675 void cmSystemTools::EnableVSConsoleOutput()
1677 // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
1678 // display output to the console unless this environment variable is
1679 // set. We need it to capture the output of these build tools.
1680 // Note for future work that one could pass "/out \\.\pipe\NAME" to
1681 // either of these executables where NAME is created with
1682 // CreateNamedPipe. This would bypass the internal buffering of the
1683 // output and allow it to be captured on the fly.
1685 cmSystemTools::PutEnv("vsconsoleoutput=1");
1689 bool cmSystemTools::IsPathToFramework(const char* path)
1691 if(cmSystemTools::FileIsFullPath(path))
1693 std::string libname = path;
1694 if(libname.find(".framework") == libname.size()+1-sizeof(".framework"))
1702 bool cmSystemTools::CreateTar(const char* outFileName,
1703 const std::vector<cmStdString>& files,
1704 bool gzip, bool bzip2, bool verbose)
1706 #if defined(CMAKE_BUILD_WITH_CMAKE)
1707 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1708 std::ofstream fout(outFileName, std::ios::out | cmsys_ios_binary);
1711 std::string e = "Cannot open output file \"";
1714 e += cmSystemTools::GetLastSystemError();
1715 cmSystemTools::Error(e.c_str());
1718 cmArchiveWrite a(fout, (gzip? cmArchiveWrite::CompressGZip :
1719 (bzip2? cmArchiveWrite::CompressBZip2 :
1720 cmArchiveWrite::CompressNone)),
1721 cmArchiveWrite::TypeTAR);
1722 a.SetVerbose(verbose);
1723 for(std::vector<cmStdString>::const_iterator i = files.begin();
1724 i != files.end(); ++i)
1726 std::string path = *i;
1727 if(cmSystemTools::FileIsFullPath(path.c_str()))
1729 // Get the relative path to the file.
1730 path = cmSystemTools::RelativePath(cwd.c_str(), path.c_str());
1739 cmSystemTools::Error(a.GetError().c_str());
1752 #if defined(CMAKE_BUILD_WITH_CMAKE)
1754 #define BSDTAR_FILESIZE_PRINTF "%lu"
1755 #define BSDTAR_FILESIZE_TYPE unsigned long
1757 list_item_verbose(FILE *out, struct archive_entry *entry)
1766 size_t gs_width = 13;
1769 * We avoid collecting the entire list in memory at once by
1770 * listing things as we see them. However, that also means we can't
1771 * just pre-compute the field widths. Instead, we start with guesses
1772 * and just widen them as necessary. These numbers are completely
1779 fprintf(out, "%s %d ",
1780 archive_entry_strmode(entry),
1781 archive_entry_nlink(entry));
1783 /* Use uname if it's present, else uid. */
1784 p = archive_entry_uname(entry);
1785 if ((p == NULL) || (*p == '\0'))
1787 sprintf(tmp, "%lu ",
1788 (unsigned long)archive_entry_uid(entry));
1796 fprintf(out, "%-*s ", (int)u_width, p);
1797 /* Use gname if it's present, else gid. */
1798 p = archive_entry_gname(entry);
1799 if (p != NULL && p[0] != '\0')
1801 fprintf(out, "%s", p);
1807 (unsigned long)archive_entry_gid(entry));
1809 fprintf(out, "%s", tmp);
1813 * Print device number or file size, right-aligned so as to make
1814 * total width of group and devnum/filesize fields be gs_width.
1815 * If gs_width is too small, grow it.
1817 if (archive_entry_filetype(entry) == AE_IFCHR
1818 || archive_entry_filetype(entry) == AE_IFBLK)
1820 sprintf(tmp, "%lu,%lu",
1821 (unsigned long)archive_entry_rdevmajor(entry),
1822 (unsigned long)archive_entry_rdevminor(entry));
1827 * Note the use of platform-dependent macros to format
1828 * the filesize here. We need the format string and the
1829 * corresponding type for the cast.
1831 sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
1832 (BSDTAR_FILESIZE_TYPE)archive_entry_size(entry));
1834 if (w + strlen(tmp) >= gs_width)
1836 gs_width = w+strlen(tmp)+1;
1838 fprintf(out, "%*s", (int)(gs_width - w), tmp);
1840 /* Format the time using 'ls -l' conventions. */
1841 tim = archive_entry_mtime(entry);
1842 #define HALF_YEAR (time_t)365 * 86400 / 2
1843 #if defined(_WIN32) && !defined(__CYGWIN__)
1844 /* Windows' strftime function does not support %e format. */
1845 #define DAY_FMT "%d"
1847 #define DAY_FMT "%e" /* Day number without leading zeros */
1849 if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
1851 fmt = DAY_FMT " %b %Y";
1855 fmt = DAY_FMT " %b %H:%M";
1857 strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
1858 fprintf(out, " %s ", tmp);
1859 fprintf(out, "%s", archive_entry_pathname(entry));
1861 /* Extra information for links. */
1862 if (archive_entry_hardlink(entry)) /* Hard link */
1864 fprintf(out, " link to %s",
1865 archive_entry_hardlink(entry));
1867 else if (archive_entry_symlink(entry)) /* Symbolic link */
1869 fprintf(out, " -> %s", archive_entry_symlink(entry));
1873 # pragma warn -8066 /* unreachable code */
1876 long copy_data(struct archive *ar, struct archive *aw)
1881 #if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
1882 __LA_INT64_T offset;
1889 r = archive_read_data_block(ar, &buff, &size, &offset);
1890 if (r == ARCHIVE_EOF)
1892 return (ARCHIVE_OK);
1894 if (r != ARCHIVE_OK)
1898 r = archive_write_data_block(aw, buff, size, offset);
1899 if (r != ARCHIVE_OK)
1901 cmSystemTools::Message("archive_write_data_block()",
1902 archive_error_string(aw));
1909 bool extract_tar(const char* outFileName, bool verbose,
1912 struct archive* a = archive_read_new();
1913 struct archive *ext = archive_write_disk_new();
1914 archive_read_support_compression_all(a);
1915 archive_read_support_format_all(a);
1916 struct archive_entry *entry;
1917 int r = archive_read_open_file(a, outFileName, 10240);
1920 cmSystemTools::Error("Problem with archive_read_open_file(): ",
1921 archive_error_string(a));
1926 r = archive_read_next_header(a, &entry);
1927 if (r == ARCHIVE_EOF)
1931 if (r != ARCHIVE_OK)
1933 cmSystemTools::Error("Problem with archive_read_next_header(): ",
1934 archive_error_string(a));
1936 if (verbose && extract)
1938 cmSystemTools::Stdout("x ");
1939 cmSystemTools::Stdout(archive_entry_pathname(entry));
1941 if(verbose && !extract)
1943 list_item_verbose(stdout, entry);
1947 cmSystemTools::Stdout(archive_entry_pathname(entry));
1951 r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME);
1952 if (r != ARCHIVE_OK)
1954 cmSystemTools::Error(
1955 "Problem with archive_write_disk_set_options(): ",
1956 archive_error_string(ext));
1959 r = archive_write_header(ext, entry);
1960 if (r != ARCHIVE_OK)
1962 cmSystemTools::Error("Problem with archive_write_header(): ",
1963 archive_error_string(ext));
1964 cmSystemTools::Error("Current file:",
1965 archive_entry_pathname(entry));
1970 r = archive_write_finish_entry(ext);
1971 if (r != ARCHIVE_OK)
1973 cmSystemTools::Error("Problem with archive_write_finish_entry(): ",
1974 archive_error_string(ext));
1978 if (verbose || !extract)
1980 cmSystemTools::Stdout("\n");
1983 archive_read_close(a);
1984 archive_read_finish(a);
1991 bool cmSystemTools::ExtractTar(const char* outFileName,
1992 bool , bool verbose)
1994 #if defined(CMAKE_BUILD_WITH_CMAKE)
1995 return extract_tar(outFileName, verbose, true);
2003 bool cmSystemTools::ListTar(const char* outFileName,
2007 #if defined(CMAKE_BUILD_WITH_CMAKE)
2008 return extract_tar(outFileName, verbose, false);
2016 int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
2018 std::vector<char>& out,
2019 std::vector<char>& err)
2022 std::vector<char>::iterator outiter = out.begin();
2023 std::vector<char>::iterator erriter = err.begin();
2026 // Check for a newline in stdout.
2027 for(;outiter != out.end(); ++outiter)
2029 if((*outiter == '\r') && ((outiter+1) == out.end()))
2033 else if(*outiter == '\n' || *outiter == '\0')
2035 std::vector<char>::size_type length = outiter-out.begin();
2036 if(length > 1 && *(outiter-1) == '\r')
2042 line.append(&out[0], length);
2044 out.erase(out.begin(), outiter+1);
2045 return cmsysProcess_Pipe_STDOUT;
2049 // Check for a newline in stderr.
2050 for(;erriter != err.end(); ++erriter)
2052 if((*erriter == '\r') && ((erriter+1) == err.end()))
2056 else if(*erriter == '\n' || *erriter == '\0')
2058 std::vector<char>::size_type length = erriter-err.begin();
2059 if(length > 1 && *(erriter-1) == '\r')
2065 line.append(&err[0], length);
2067 err.erase(err.begin(), erriter+1);
2068 return cmsysProcess_Pipe_STDERR;
2072 // No newlines found. Wait for more data from the process.
2075 int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
2076 if(pipe == cmsysProcess_Pipe_Timeout)
2078 // Timeout has been exceeded.
2081 else if(pipe == cmsysProcess_Pipe_STDOUT)
2083 // Append to the stdout buffer.
2084 std::vector<char>::size_type size = out.size();
2085 out.insert(out.end(), data, data+length);
2086 outiter = out.begin()+size;
2088 else if(pipe == cmsysProcess_Pipe_STDERR)
2090 // Append to the stderr buffer.
2091 std::vector<char>::size_type size = err.size();
2092 err.insert(err.end(), data, data+length);
2093 erriter = err.begin()+size;
2095 else if(pipe == cmsysProcess_Pipe_None)
2097 // Both stdout and stderr pipes have broken. Return leftover data.
2100 line.append(&out[0], outiter-out.begin());
2101 out.erase(out.begin(), out.end());
2102 return cmsysProcess_Pipe_STDOUT;
2104 else if(!err.empty())
2106 line.append(&err[0], erriter-err.begin());
2107 err.erase(err.begin(), err.end());
2108 return cmsysProcess_Pipe_STDERR;
2112 return cmsysProcess_Pipe_None;
2118 void cmSystemTools::DoNotInheritStdPipes()
2121 // Check to see if we are attached to a console
2122 // if so, then do not stop the inherited pipes
2123 // or stdout and stderr will not show up in dos
2125 CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
2126 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
2127 if(GetConsoleScreenBufferInfo(hOut, &hOutInfo))
2132 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
2133 DuplicateHandle(GetCurrentProcess(), out,
2134 GetCurrentProcess(), &out, 0, FALSE,
2135 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2136 SetStdHandle(STD_OUTPUT_HANDLE, out);
2139 HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
2140 DuplicateHandle(GetCurrentProcess(), out,
2141 GetCurrentProcess(), &out, 0, FALSE,
2142 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2143 SetStdHandle(STD_ERROR_HANDLE, out);
2148 //----------------------------------------------------------------------------
2149 bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
2151 #if defined(_WIN32) && !defined(__CYGWIN__)
2152 cmSystemToolsWindowsHandle hFrom =
2153 CreateFile(fromFile, GENERIC_READ, FILE_SHARE_READ, 0,
2154 OPEN_EXISTING, 0, 0);
2155 cmSystemToolsWindowsHandle hTo =
2156 CreateFile(toFile, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2161 FILETIME timeCreation;
2162 FILETIME timeLastAccess;
2163 FILETIME timeLastWrite;
2164 if(!GetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite))
2168 if(!SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite))
2173 struct stat fromStat;
2174 if(stat(fromFile, &fromStat) < 0)
2180 buf.actime = fromStat.st_atime;
2181 buf.modtime = fromStat.st_mtime;
2182 if(utime(toFile, &buf) < 0)
2190 //----------------------------------------------------------------------------
2191 cmSystemToolsFileTime* cmSystemTools::FileTimeNew()
2193 return new cmSystemToolsFileTime;
2196 //----------------------------------------------------------------------------
2197 void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime* t)
2202 //----------------------------------------------------------------------------
2203 bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
2205 #if defined(_WIN32) && !defined(__CYGWIN__)
2206 cmSystemToolsWindowsHandle h =
2207 CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
2212 if(!GetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2218 if(stat(fname, &st) < 0)
2222 t->timeBuf.actime = st.st_atime;
2223 t->timeBuf.modtime = st.st_mtime;
2228 //----------------------------------------------------------------------------
2229 bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
2231 #if defined(_WIN32) && !defined(__CYGWIN__)
2232 cmSystemToolsWindowsHandle h =
2233 CreateFile(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2238 if(!SetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2243 if(utime(fname, &t->timeBuf) < 0)
2251 //----------------------------------------------------------------------------
2253 # ifndef CRYPT_SILENT
2254 # define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header. */
2256 static int WinCryptRandom(void* data, size_t size)
2259 HCRYPTPROV hProvider = 0;
2260 if(CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
2261 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
2263 result = CryptGenRandom(hProvider, (DWORD)size, (BYTE*)data)? 1:0;
2264 CryptReleaseContext(hProvider, 0);
2270 //----------------------------------------------------------------------------
2271 unsigned int cmSystemTools::RandomSeed()
2273 #if defined(_WIN32) && !defined(__CYGWIN__)
2274 unsigned int seed = 0;
2276 // Try using a real random source.
2277 if(WinCryptRandom(&seed, sizeof(seed)))
2282 // Fall back to the time and pid.
2284 GetSystemTimeAsFileTime(&ft);
2285 unsigned int t1 = static_cast<unsigned int>(ft.dwHighDateTime);
2286 unsigned int t2 = static_cast<unsigned int>(ft.dwLowDateTime);
2287 unsigned int pid = static_cast<unsigned int>(GetCurrentProcessId());
2288 return t1 ^ t2 ^ pid;
2292 unsigned int integer;
2293 char bytes[sizeof(unsigned int)];
2296 // Try using a real random source.
2297 std::ifstream fin("/dev/urandom");
2298 if(fin && fin.read(seed.bytes, sizeof(seed)) &&
2299 fin.gcount() == sizeof(seed))
2301 return seed.integer;
2304 // Fall back to the time and pid.
2306 gettimeofday(&t, 0);
2307 unsigned int pid = static_cast<unsigned int>(getpid());
2308 unsigned int tv_sec = static_cast<unsigned int>(t.tv_sec);
2309 unsigned int tv_usec = static_cast<unsigned int>(t.tv_usec);
2310 // Since tv_usec never fills more than 11 bits we shift it to fill
2311 // in the slow-changing high-order bits of tv_sec.
2312 return tv_sec ^ (tv_usec << 21) ^ pid;
2316 //----------------------------------------------------------------------------
2317 static std::string cmSystemToolsExecutableDirectory;
2318 void cmSystemTools::FindExecutableDirectory(const char* argv0)
2320 #if defined(_WIN32) && !defined(__CYGWIN__)
2321 (void)argv0; // ignore this on windows
2322 char modulepath[_MAX_PATH];
2323 ::GetModuleFileName(NULL, modulepath, sizeof(modulepath));
2324 cmSystemToolsExecutableDirectory =
2325 cmSystemTools::GetFilenamePath(modulepath);
2328 std::string errorMsg;
2330 if(cmSystemTools::FindProgramPath(argv0, exe, errorMsg))
2333 exe = cmSystemTools::GetRealPath(exe.c_str());
2334 cmSystemToolsExecutableDirectory =
2335 cmSystemTools::GetFilenamePath(exe.c_str());
2344 //----------------------------------------------------------------------------
2345 const char* cmSystemTools::GetExecutableDirectory()
2347 return cmSystemToolsExecutableDirectory.c_str();
2350 //----------------------------------------------------------------------------
2351 #if defined(CMAKE_BUILD_WITH_CMAKE)
2352 void cmSystemTools::MakefileColorEcho(int color, const char* message,
2353 bool newline, bool enabled)
2355 // On some platforms (an MSYS prompt) cmsysTerminal may not be able
2356 // to determine whether the stream is displayed on a tty. In this
2357 // case it assumes no unless we tell it otherwise. Since we want
2358 // color messages to be displayed for users we will assume yes.
2359 // However, we can test for some situations when the answer is most
2361 int assumeTTY = cmsysTerminal_Color_AssumeTTY;
2362 if(cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
2363 cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
2364 cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE"))
2366 // Avoid printing color escapes during dashboard builds.
2372 cmsysTerminal_cfprintf(color | assumeTTY, stdout, "%s%s",
2373 message, newline? "\n" : "");
2377 // Color is disabled. Print without color.
2378 fprintf(stdout, "%s%s", message, newline? "\n" : "");
2383 //----------------------------------------------------------------------------
2384 bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
2385 std::string& soname)
2387 // For ELF shared libraries use a real parser to get the correct
2389 #if defined(CMAKE_USE_ELF_PARSER)
2390 cmELF elf(fullPath.c_str());
2393 return elf.GetSOName(soname);
2397 // If the file is not a symlink we have no guess for its soname.
2398 if(!cmSystemTools::FileIsSymlink(fullPath.c_str()))
2402 if(!cmSystemTools::ReadSymlink(fullPath.c_str(), soname))
2407 // If the symlink has a path component we have no guess for the soname.
2408 if(!cmSystemTools::GetFilenamePath(soname).empty())
2413 // If the symlink points at an extended version of the same name
2414 // assume it is the soname.
2415 std::string name = cmSystemTools::GetFilenameName(fullPath);
2416 if(soname.length() > name.length() &&
2417 soname.substr(0, name.length()) == name)
2424 //----------------------------------------------------------------------------
2425 #if defined(CMAKE_USE_ELF_PARSER)
2426 std::string::size_type cmSystemToolsFindRPath(std::string const& have,
2427 std::string const& want)
2429 // Search for the desired rpath.
2430 std::string::size_type pos = have.find(want);
2432 // If the path is not present we are done.
2433 if(pos == std::string::npos)
2438 // Build a regex to match a properly separated path instance.
2439 std::string regex_str = "(^|:)(";
2440 for(std::string::const_iterator i = want.begin(); i != want.end(); ++i)
2443 if(!(('a' <= ch && ch <= 'z') ||
2444 ('A' <= ch && ch <= 'Z') ||
2445 ('0' <= ch && ch <= '9')))
2447 // Escape the non-alphanumeric character.
2450 // Store the character.
2451 regex_str.append(1, static_cast<char>(ch));
2453 regex_str += ")(:|$)";
2455 // Look for the separated path.
2456 cmsys::RegularExpression regex(regex_str.c_str());
2457 if(regex.find(have))
2459 // Return the position of the path portion.
2460 return regex.start(2);
2464 // The desired rpath was not found.
2465 return std::string::npos;
2470 #if defined(CMAKE_USE_ELF_PARSER)
2471 struct cmSystemToolsRPathInfo
2473 unsigned long Position;
2480 //----------------------------------------------------------------------------
2481 bool cmSystemTools::ChangeRPath(std::string const& file,
2482 std::string const& oldRPath,
2483 std::string const& newRPath,
2487 #if defined(CMAKE_USE_ELF_PARSER)
2493 cmSystemToolsRPathInfo rp[2];
2495 // Parse the ELF binary.
2496 cmELF elf(file.c_str());
2498 // Get the RPATH and RUNPATH entries from it.
2500 cmELF::StringEntry const* se[2] = {0, 0};
2501 const char* se_name[2] = {0, 0};
2502 if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2504 se[se_count] = se_rpath;
2505 se_name[se_count] = "RPATH";
2508 if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2510 se[se_count] = se_runpath;
2511 se_name[se_count] = "RUNPATH";
2516 if(newRPath.empty())
2518 // The new rpath is empty and there is no rpath anyway so it is
2526 *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
2527 *emsg += elf.GetErrorMessage();
2533 for(int i=0; i < se_count; ++i)
2535 // If both RPATH and RUNPATH refer to the same string literal it
2536 // needs to be changed only once.
2537 if(rp_count && rp[0].Position == se[i]->Position)
2542 // Make sure the current rpath contains the old rpath.
2543 std::string::size_type pos =
2544 cmSystemToolsFindRPath(se[i]->Value, oldRPath);
2545 if(pos == std::string::npos)
2547 // If it contains the new rpath instead then it is okay.
2548 if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
2555 e << "The current " << se_name[i] << " is:\n"
2556 << " " << se[i]->Value << "\n"
2557 << "which does not contain:\n"
2558 << " " << oldRPath << "\n"
2559 << "as was expected.";
2565 // Store information about the entry in the file.
2566 rp[rp_count].Position = se[i]->Position;
2567 rp[rp_count].Size = se[i]->Size;
2568 rp[rp_count].Name = se_name[i];
2570 // Construct the new value which preserves the part of the path
2571 // not being changed.
2572 rp[rp_count].Value = se[i]->Value.substr(0, pos);
2573 rp[rp_count].Value += newRPath;
2574 rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
2577 // Make sure there is enough room to store the new rpath and at
2578 // least one null terminator.
2579 if(rp[rp_count].Size < rp[rp_count].Value.length()+1)
2583 *emsg = "The replacement path is too long for the ";
2584 *emsg += se_name[i];
2590 // This entry is ready for update.
2595 // If no runtime path needs to be changed, we are done.
2602 // Open the file for update.
2603 std::ofstream f(file.c_str(),
2604 std::ios::in | std::ios::out | std::ios::binary);
2609 *emsg = "Error opening file for update.";
2614 // Store the new RPATH and RUNPATH strings.
2615 for(int i=0; i < rp_count; ++i)
2617 // Seek to the RPATH position.
2618 if(!f.seekp(rp[i].Position))
2622 *emsg = "Error seeking to ";
2623 *emsg += rp[i].Name;
2624 *emsg += " position.";
2629 // Write the new rpath. Follow it with enough null terminators to
2630 // fill the string table entry.
2632 for(unsigned long j=rp[i].Value.length(); j < rp[i].Size; ++j)
2637 // Make sure it wrote correctly.
2642 *emsg = "Error writing the new ";
2643 *emsg += rp[i].Name;
2644 *emsg += " string to the file.";
2651 // Everything was updated successfully.
2667 //----------------------------------------------------------------------------
2668 bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
2669 const char* lhss, const char* rhss)
2671 unsigned int lhs[4] = {0,0,0,0};
2672 unsigned int rhs[4] = {0,0,0,0};
2673 sscanf(lhss, "%u.%u.%u.%u", &lhs[0], &lhs[1], &lhs[2], &lhs[3]);
2674 sscanf(rhss, "%u.%u.%u.%u", &rhs[0], &rhs[1], &rhs[2], &rhs[3]);
2676 // Do component-wise comparison.
2677 for(unsigned int i=0; i < 4; ++i)
2681 // lhs < rhs, so true if operation is LESS
2682 return op == cmSystemTools::OP_LESS;
2684 else if(lhs[i] > rhs[i])
2686 // lhs > rhs, so true if operation is GREATER
2687 return op == cmSystemTools::OP_GREATER;
2690 // lhs == rhs, so true if operation is EQUAL
2691 return op == cmSystemTools::OP_EQUAL;
2694 //----------------------------------------------------------------------------
2695 bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
2698 #if defined(CMAKE_USE_ELF_PARSER)
2704 unsigned long zeroPosition[2] = {0,0};
2705 unsigned long zeroSize[2] = {0,0};
2706 unsigned long bytesBegin = 0;
2707 std::vector<char> bytes;
2709 // Parse the ELF binary.
2710 cmELF elf(file.c_str());
2712 // Get the RPATH and RUNPATH entries from it and sort them by index
2713 // in the dynamic section header.
2715 cmELF::StringEntry const* se[2] = {0, 0};
2716 if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2718 se[se_count++] = se_rpath;
2720 if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2722 se[se_count++] = se_runpath;
2726 // There is no RPATH or RUNPATH anyway.
2729 if(se_count == 2 && se[1]->IndexInSection < se[0]->IndexInSection)
2731 cmsys_stl::swap(se[0], se[1]);
2734 // Get the size of the dynamic section header.
2735 unsigned int count = elf.GetDynamicEntryCount();
2738 // This should happen only for invalid ELF files where a DT_NULL
2739 // appears before the end of the table.
2742 *emsg = "DYNAMIC section contains a DT_NULL before the end.";
2747 // Save information about the string entries to be zeroed.
2748 zeroCount = se_count;
2749 for(int i=0; i < se_count; ++i)
2751 zeroPosition[i] = se[i]->Position;
2752 zeroSize[i] = se[i]->Size;
2755 // Get the range of file positions corresponding to each entry and
2756 // the rest of the table after them.
2757 unsigned long entryBegin[3] = {0,0,0};
2758 unsigned long entryEnd[2] = {0,0};
2759 for(int i=0; i < se_count; ++i)
2761 entryBegin[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection);
2762 entryEnd[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection+1);
2764 entryBegin[se_count] = elf.GetDynamicEntryPosition(count);
2766 // The data are to be written over the old table entries starting at
2767 // the first one being removed.
2768 bytesBegin = entryBegin[0];
2769 unsigned long bytesEnd = entryBegin[se_count];
2771 // Allocate a buffer to hold the part of the file to be written.
2772 // Initialize it with zeros.
2773 bytes.resize(bytesEnd - bytesBegin, 0);
2775 // Read the part of the DYNAMIC section header that will move.
2776 // The remainder of the buffer will be left with zeros which
2777 // represent a DT_NULL entry.
2778 char* data = &bytes[0];
2779 for(int i=0; i < se_count; ++i)
2781 // Read data between the entries being removed.
2782 unsigned long sz = entryBegin[i+1] - entryEnd[i];
2783 if(sz > 0 && !elf.ReadBytes(entryEnd[i], sz, data))
2787 *emsg = "Failed to read DYNAMIC section header.";
2795 // Open the file for update.
2796 std::ofstream f(file.c_str(),
2797 std::ios::in | std::ios::out | std::ios::binary);
2802 *emsg = "Error opening file for update.";
2807 // Write the new DYNAMIC table header.
2808 if(!f.seekp(bytesBegin))
2812 *emsg = "Error seeking to DYNAMIC table header for RPATH.";
2816 if(!f.write(&bytes[0], bytes.size()))
2820 *emsg = "Error replacing DYNAMIC table header.";
2825 // Fill the RPATH and RUNPATH strings with zero bytes.
2826 for(int i=0; i < zeroCount; ++i)
2828 if(!f.seekp(zeroPosition[i]))
2832 *emsg = "Error seeking to RPATH position.";
2836 for(unsigned long j=0; j < zeroSize[i]; ++j)
2844 *emsg = "Error writing the empty rpath string to the file.";
2850 // Everything was updated successfully.
2864 //----------------------------------------------------------------------------
2865 bool cmSystemTools::CheckRPath(std::string const& file,
2866 std::string const& newRPath)
2868 #if defined(CMAKE_USE_ELF_PARSER)
2869 // Parse the ELF binary.
2870 cmELF elf(file.c_str());
2872 // Get the RPATH or RUNPATH entry from it.
2873 cmELF::StringEntry const* se = elf.GetRPath();
2876 se = elf.GetRunPath();
2879 // Make sure the current rpath contains the new rpath.
2880 if(newRPath.empty())
2890 cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
2903 //----------------------------------------------------------------------------
2904 bool cmSystemTools::RepeatedRemoveDirectory(const char* dir)
2906 // Windows sometimes locks files temporarily so try a few times.
2907 for(int i = 0; i < 10; ++i)
2909 if(cmSystemTools::RemoveADirectory(dir))
2913 cmSystemTools::Delay(100);
2918 //----------------------------------------------------------------------------
2919 std::vector<std::string> cmSystemTools::tokenize(const std::string& str,
2920 const std::string& sep)
2922 std::vector<std::string> tokens;
2923 std::string::size_type tokend = 0;
2927 std::string::size_type tokstart=str.find_first_not_of(sep, tokend);
2928 if (tokstart==std::string::npos)
2930 break; // no more tokens
2932 tokend=str.find_first_of(sep,tokstart);
2933 if (tokend==std::string::npos)
2935 tokens.push_back(str.substr(tokstart));
2939 tokens.push_back(str.substr(tokstart,tokend-tokstart));
2941 } while (tokend!=std::string::npos);
2945 tokens.push_back("");