Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmSystemTools.cxx
blob7c4067024c5e7c9adb50b7e0262d3d71b86168a8
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmSystemTools.cxx,v $
5 Language: C++
6 Date: $Date: 2009-02-05 21:31:34 $
7 Version: $Revision: 1.389 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmSystemTools.h"
18 #include <ctype.h>
19 #include <errno.h>
20 #include <time.h>
21 #include <string.h>
23 #include <cmsys/RegularExpression.hxx>
24 #include <cmsys/Directory.hxx>
25 #include <cmsys/System.h>
26 #if defined(CMAKE_BUILD_WITH_CMAKE)
27 # include <cmsys/Terminal.h>
28 #endif
29 #include <cmsys/stl/algorithm>
31 #if defined(_WIN32)
32 # include <windows.h>
33 #else
34 # include <sys/types.h>
35 # include <unistd.h>
36 # include <utime.h>
37 # include <sys/wait.h>
38 #endif
40 #include <sys/stat.h>
42 #if defined(_WIN32) && \
43 (defined(_MSC_VER) || defined(__WATCOMC__) || \
44 defined(__BORLANDC__) || defined(__MINGW32__))
45 # include <io.h>
46 #endif
48 #if defined(CMAKE_BUILD_WITH_CMAKE)
49 # include <libtar/libtar.h>
50 # include <memory> // auto_ptr
51 # include <fcntl.h>
52 # include <cm_zlib.h>
53 # include <cmsys/MD5.h>
54 #endif
56 #if defined(CMAKE_USE_ELF_PARSER)
57 # include "cmELF.h"
58 #endif
60 class cmSystemToolsFileTime
62 public:
63 #if defined(_WIN32) && !defined(__CYGWIN__)
64 FILETIME timeCreation;
65 FILETIME timeLastAccess;
66 FILETIME timeLastWrite;
67 #else
68 struct utimbuf timeBuf;
69 #endif
72 #if defined(__sgi) && !defined(__GNUC__)
73 # pragma set woff 1375 /* base class destructor not virtual */
74 #endif
76 #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
77 // For GetEnvironmentVariables
78 # if defined(_WIN32)
79 extern __declspec( dllimport ) char** environ;
80 # else
81 extern char** environ;
82 # endif
83 #endif
85 #ifdef _WIN32
86 class cmSystemToolsWindowsHandle
88 public:
89 cmSystemToolsWindowsHandle(HANDLE h): handle_(h) {}
90 ~cmSystemToolsWindowsHandle()
92 if(this->handle_ != INVALID_HANDLE_VALUE)
94 CloseHandle(this->handle_);
97 operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; }
98 bool operator !() const { return this->handle_ == INVALID_HANDLE_VALUE; }
99 operator HANDLE() const { return this->handle_; }
100 private:
101 HANDLE handle_;
103 #endif
105 bool cmSystemTools::s_RunCommandHideConsole = false;
106 bool cmSystemTools::s_DisableRunCommandOutput = false;
107 bool cmSystemTools::s_ErrorOccured = false;
108 bool cmSystemTools::s_FatalErrorOccured = false;
109 bool cmSystemTools::s_DisableMessages = false;
110 bool cmSystemTools::s_ForceUnixPaths = false;
112 std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com";
113 void cmSystemTools::SetWindows9xComspecSubstitute(const char* str)
115 if ( str )
117 cmSystemTools::s_Windows9xComspecSubstitute = str;
120 const char* cmSystemTools::GetWindows9xComspecSubstitute()
122 return cmSystemTools::s_Windows9xComspecSubstitute.c_str();
125 void (*cmSystemTools::s_ErrorCallback)(const char*, const char*,
126 bool&, void*);
127 void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*);
128 void* cmSystemTools::s_ErrorCallbackClientData = 0;
129 void* cmSystemTools::s_StdoutCallbackClientData = 0;
131 // replace replace with with as many times as it shows up in source.
132 // write the result into source.
133 #if defined(_WIN32) && !defined(__CYGWIN__)
134 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view)
136 // Regular expression to match anything inside [...] that begins in HKEY.
137 // Note that there is a special rule for regular expressions to match a
138 // close square-bracket inside a list delimited by square brackets.
139 // The "[^]]" part of this expression will match any character except
140 // a close square-bracket. The ']' character must be the first in the
141 // list of characters inside the [^...] block of the expression.
142 cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
144 // check for black line or comment
145 while (regEntry.find(source))
147 // the arguments are the second match
148 std::string key = regEntry.match(1);
149 std::string val;
150 if (ReadRegistryValue(key.c_str(), val, view))
152 std::string reg = "[";
153 reg += key + "]";
154 cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
156 else
158 std::string reg = "[";
159 reg += key + "]";
160 cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
164 #else
165 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64)
167 cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
168 while (regEntry.find(source))
170 // the arguments are the second match
171 std::string key = regEntry.match(1);
172 std::string val;
173 std::string reg = "[";
174 reg += key + "]";
175 cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
179 #endif
181 std::string cmSystemTools::EscapeQuotes(const char* str)
183 std::string result = "";
184 for(const char* ch = str; *ch != '\0'; ++ch)
186 if(*ch == '"')
188 result += '\\';
190 result += *ch;
192 return result;
195 std::string cmSystemTools::EscapeSpaces(const char* str)
197 #if defined(_WIN32) && !defined(__CYGWIN__)
198 bool useDoubleQ = true;
199 #else
200 bool useDoubleQ = false;
201 #endif
202 if(cmSystemTools::s_ForceUnixPaths)
204 useDoubleQ = false;
207 if(useDoubleQ)
209 std::string result;
211 // if there are spaces
212 std::string temp = str;
213 if (temp.find(" ") != std::string::npos &&
214 temp.find("\"")==std::string::npos)
216 result = "\"";
217 result += str;
218 result += "\"";
219 return result;
221 return str;
223 else
225 std::string result = "";
226 for(const char* ch = str; *ch != '\0'; ++ch)
228 if(*ch == ' ')
230 result += '\\';
232 result += *ch;
234 return result;
239 std::string cmSystemTools::RemoveEscapes(const char* s)
241 std::string result = "";
242 for(const char* ch = s; *ch; ++ch)
244 if(*ch == '\\' && *(ch+1) != ';')
246 ++ch;
247 switch (*ch)
249 case '\\': result.insert(result.end(), '\\'); break;
250 case '"': result.insert(result.end(), '"'); break;
251 case ' ': result.insert(result.end(), ' '); break;
252 case 't': result.insert(result.end(), '\t'); break;
253 case 'n': result.insert(result.end(), '\n'); break;
254 case 'r': result.insert(result.end(), '\r'); break;
255 case '#': result.insert(result.end(), '#'); break;
256 case '(': result.insert(result.end(), '('); break;
257 case ')': result.insert(result.end(), ')'); break;
258 case '0': result.insert(result.end(), '\0'); break;
259 case '\0':
261 cmSystemTools::Error("Trailing backslash in argument:\n", s);
262 return result;
264 default:
266 std::string chStr(1, *ch);
267 cmSystemTools::Error("Invalid escape sequence \\", chStr.c_str(),
268 "\nin argument ", s);
272 else
274 result.insert(result.end(), *ch);
277 return result;
280 void cmSystemTools::Error(const char* m1, const char* m2,
281 const char* m3, const char* m4)
283 std::string message = "CMake Error: ";
284 if(m1)
286 message += m1;
288 if(m2)
290 message += m2;
292 if(m3)
294 message += m3;
296 if(m4)
298 message += m4;
300 cmSystemTools::s_ErrorOccured = true;
301 cmSystemTools::Message(message.c_str(),"Error");
305 void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData)
307 s_ErrorCallback = f;
308 s_ErrorCallbackClientData = clientData;
311 void cmSystemTools::SetStdoutCallback(StdoutCallback f, void* clientData)
313 s_StdoutCallback = f;
314 s_StdoutCallbackClientData = clientData;
317 void cmSystemTools::Stdout(const char* s)
319 if(s_StdoutCallback)
321 (*s_StdoutCallback)(s, static_cast<int>(strlen(s)),
322 s_StdoutCallbackClientData);
324 else
326 std::cout << s;
327 std::cout.flush();
331 void cmSystemTools::Stdout(const char* s, int length)
333 if(s_StdoutCallback)
335 (*s_StdoutCallback)(s, length, s_StdoutCallbackClientData);
337 else
339 std::cout.write(s, length);
340 std::cout.flush();
344 void cmSystemTools::Message(const char* m1, const char *title)
346 if(s_DisableMessages)
348 return;
350 if(s_ErrorCallback)
352 (*s_ErrorCallback)(m1, title, s_DisableMessages,
353 s_ErrorCallbackClientData);
354 return;
356 else
358 std::cerr << m1 << std::endl << std::flush;
364 void cmSystemTools::ReportLastSystemError(const char* msg)
366 std::string m = msg;
367 m += ": System Error: ";
368 m += Superclass::GetLastSystemError();
369 cmSystemTools::Error(m.c_str());
373 bool cmSystemTools::IsOn(const char* val)
375 if (!val)
377 return false;
379 std::basic_string<char> v = val;
381 for(std::basic_string<char>::iterator c = v.begin();
382 c != v.end(); c++)
384 *c = toupper(*c);
386 return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y");
389 bool cmSystemTools::IsNOTFOUND(const char* val)
391 size_t len = strlen(val);
392 const char* notfound = "-NOTFOUND";
393 const size_t lenNotFound = 9;
394 if(len < lenNotFound-1)
396 return false;
398 if(len == lenNotFound-1)
400 return ( strcmp(val, "NOTFOUND") == 0);
402 return ((strncmp((val + (len - lenNotFound)), notfound, lenNotFound) == 0));
406 bool cmSystemTools::IsOff(const char* val)
408 if (!val || strlen(val) == 0)
410 return true;
412 std::basic_string<char> v = val;
414 for(std::basic_string<char>::iterator c = v.begin();
415 c != v.end(); c++)
417 *c = toupper(*c);
419 return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" ||
420 v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE");
423 //----------------------------------------------------------------------------
424 void cmSystemTools::ParseWindowsCommandLine(const char* command,
425 std::vector<std::string>& args)
427 // See the MSDN document "Parsing C Command-Line Arguments" at
428 // http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx for rules
429 // of parsing the windows command line.
431 bool in_argument = false;
432 bool in_quotes = false;
433 int backslashes = 0;
434 std::string arg;
435 for(const char* c = command;*c; ++c)
437 if(*c == '\\')
439 ++backslashes;
440 in_argument = true;
442 else if(*c == '"')
444 int backslash_pairs = backslashes >> 1;
445 int backslash_escaped = backslashes & 1;
446 arg.append(backslash_pairs, '\\');
447 backslashes = 0;
448 if(backslash_escaped)
450 /* An odd number of backslashes precede this quote.
451 It is escaped. */
452 arg.append(1, '"');
454 else
456 /* An even number of backslashes precede this quote.
457 It is not escaped. */
458 in_quotes = !in_quotes;
460 in_argument = true;
462 else
464 arg.append(backslashes, '\\');
465 backslashes = 0;
466 if(isspace(*c))
468 if(in_quotes)
470 arg.append(1, *c);
472 else if(in_argument)
474 args.push_back(arg);
475 arg = "";
476 in_argument = false;
479 else
481 in_argument = true;
482 arg.append(1, *c);
486 arg.append(backslashes, '\\');
487 if(in_argument)
489 args.push_back(arg);
493 std::string cmSystemTools::EscapeWindowsShellArgument(const char* arg,
494 int shell_flags)
496 char local_buffer[1024];
497 char* buffer = local_buffer;
498 int size = cmsysSystem_Shell_GetArgumentSizeForWindows(arg, shell_flags);
499 if(size > 1024)
501 buffer = new char[size];
503 cmsysSystem_Shell_GetArgumentForWindows(arg, buffer, shell_flags);
504 std::string result(buffer);
505 if(buffer != local_buffer)
507 delete [] buffer;
509 return result;
512 std::vector<cmStdString> cmSystemTools::ParseArguments(const char* command)
514 std::vector<cmStdString> args;
515 std::string arg;
517 bool win_path = false;
519 if ( command[0] != '/' && command[1] == ':' && command[2] == '\\' ||
520 command[0] == '\"' && command[1] != '/' && command[2] == ':'
521 && command[3] == '\\' ||
522 command[0] == '\'' && command[1] != '/' && command[2] == ':'
523 && command[3] == '\\' ||
524 command[0] == '\\' && command[1] == '\\')
526 win_path = true;
528 // Split the command into an argv array.
529 for(const char* c = command; *c;)
531 // Skip over whitespace.
532 while(*c == ' ' || *c == '\t')
534 ++c;
536 arg = "";
537 if(*c == '"')
539 // Parse a quoted argument.
540 ++c;
541 while(*c && *c != '"')
543 arg.append(1, *c);
544 ++c;
546 if(*c)
548 ++c;
550 args.push_back(arg);
552 else if(*c == '\'')
554 // Parse a quoted argument.
555 ++c;
556 while(*c && *c != '\'')
558 arg.append(1, *c);
559 ++c;
561 if(*c)
563 ++c;
565 args.push_back(arg);
567 else if(*c)
569 // Parse an unquoted argument.
570 while(*c && *c != ' ' && *c != '\t')
572 if(*c == '\\' && !win_path)
574 ++c;
575 if(*c)
577 arg.append(1, *c);
578 ++c;
581 else
583 arg.append(1, *c);
584 ++c;
587 args.push_back(arg);
591 return args;
595 bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
596 std::string* output ,
597 int* retVal , const char* dir ,
598 bool verbose ,
599 double timeout )
601 std::vector<const char*> argv;
602 for(std::vector<cmStdString>::const_iterator a = command.begin();
603 a != command.end(); ++a)
605 argv.push_back(a->c_str());
607 argv.push_back(0);
608 if ( output )
610 *output = "";
613 cmsysProcess* cp = cmsysProcess_New();
614 cmsysProcess_SetCommand(cp, &*argv.begin());
615 cmsysProcess_SetWorkingDirectory(cp, dir);
616 if(cmSystemTools::GetRunCommandHideConsole())
618 cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
620 cmsysProcess_SetTimeout(cp, timeout);
621 cmsysProcess_Execute(cp);
623 std::vector<char> tempOutput;
624 char* data;
625 int length;
626 if ( output || verbose )
628 while(cmsysProcess_WaitForData(cp, &data, &length, 0))
630 if(output || verbose)
632 // Translate NULL characters in the output into valid text.
633 // Visual Studio 7 puts these characters in the output of its
634 // build process.
635 for(int i=0; i < length; ++i)
637 if(data[i] == '\0')
639 data[i] = ' ';
643 if ( output )
645 tempOutput.insert(tempOutput.end(), data, data+length);
647 if(verbose)
649 cmSystemTools::Stdout(data, length);
654 cmsysProcess_WaitForExit(cp, 0);
655 if ( output && tempOutput.begin() != tempOutput.end())
657 output->append(&*tempOutput.begin(), tempOutput.size());
660 bool result = true;
661 if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
663 if ( retVal )
665 *retVal = cmsysProcess_GetExitValue(cp);
667 else
669 if ( cmsysProcess_GetExitValue(cp) != 0 )
671 result = false;
675 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
677 const char* exception_str = cmsysProcess_GetExceptionString(cp);
678 if ( verbose )
680 std::cerr << exception_str << std::endl;
682 if ( output )
684 output->append(exception_str, strlen(exception_str));
686 result = false;
688 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
690 const char* error_str = cmsysProcess_GetErrorString(cp);
691 if ( verbose )
693 std::cerr << error_str << std::endl;
695 if ( output )
697 output->append(error_str, strlen(error_str));
699 result = false;
701 else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
703 const char* error_str = "Process terminated due to timeout\n";
704 if ( verbose )
706 std::cerr << error_str << std::endl;
708 if ( output )
710 output->append(error_str, strlen(error_str));
712 result = false;
715 cmsysProcess_Delete(cp);
716 return result;
719 bool cmSystemTools::RunSingleCommand(
720 const char* command,
721 std::string* output,
722 int *retVal,
723 const char* dir,
724 bool verbose,
725 double timeout)
727 if(s_DisableRunCommandOutput)
729 verbose = false;
732 std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
734 if(args.size() < 1)
736 return false;
738 return cmSystemTools::RunSingleCommand(args, output,retVal,
739 dir, verbose, timeout);
741 bool cmSystemTools::RunCommand(const char* command,
742 std::string& output,
743 const char* dir,
744 bool verbose,
745 int timeout)
747 int dummy;
748 return cmSystemTools::RunCommand(command, output, dummy,
749 dir, verbose, timeout);
752 #if defined(WIN32) && !defined(__CYGWIN__)
753 #include "cmWin32ProcessExecution.h"
754 // use this for shell commands like echo and dir
755 bool RunCommandViaWin32(const char* command,
756 const char* dir,
757 std::string& output,
758 int& retVal,
759 bool verbose,
760 int timeout)
762 #if defined(__BORLANDC__)
763 return
764 cmWin32ProcessExecution::
765 BorlandRunCommand(command, dir, output,
766 retVal,
767 verbose, timeout,
768 cmSystemTools::GetRunCommandHideConsole());
769 #else // Visual studio
770 ::SetLastError(ERROR_SUCCESS);
771 if ( ! command )
773 cmSystemTools::Error("No command specified");
774 return false;
776 cmWin32ProcessExecution resProc;
777 if(cmSystemTools::GetRunCommandHideConsole())
779 resProc.SetHideWindows(true);
782 if ( cmSystemTools::GetWindows9xComspecSubstitute() )
784 resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
786 if ( !resProc.StartProcess(command, dir, verbose) )
788 output = resProc.GetOutput();
789 if(verbose)
791 cmSystemTools::Stdout(output.c_str());
793 return false;
795 resProc.Wait(timeout);
796 output = resProc.GetOutput();
797 retVal = resProc.GetExitValue();
798 return true;
799 #endif
802 // use this for shell commands like echo and dir
803 bool RunCommandViaSystem(const char* command,
804 const char* dir,
805 std::string& output,
806 int& retVal,
807 bool verbose)
809 std::cout << "@@ " << command << std::endl;
811 std::string commandInDir;
812 if(dir)
814 commandInDir = "cd ";
815 commandInDir += cmSystemTools::ConvertToOutputPath(dir);
816 commandInDir += " && ";
817 commandInDir += command;
819 else
821 commandInDir = command;
823 command = commandInDir.c_str();
824 std::string commandToFile = command;
825 commandToFile += " > ";
826 std::string tempFile;
827 tempFile += _tempnam(0, "cmake");
829 commandToFile += tempFile;
830 retVal = system(commandToFile.c_str());
831 std::ifstream fin(tempFile.c_str());
832 if(!fin)
834 if(verbose)
836 std::string errormsg = "RunCommand produced no output: command: \"";
837 errormsg += command;
838 errormsg += "\"";
839 errormsg += "\nOutput file: ";
840 errormsg += tempFile;
841 cmSystemTools::Error(errormsg.c_str());
843 fin.close();
844 cmSystemTools::RemoveFile(tempFile.c_str());
845 return false;
847 bool multiLine = false;
848 std::string line;
849 while(cmSystemTools::GetLineFromStream(fin, line))
851 output += line;
852 if(multiLine)
854 output += "\n";
856 multiLine = true;
858 fin.close();
859 cmSystemTools::RemoveFile(tempFile.c_str());
860 return true;
863 #else // We have popen
865 // BeOS seems to return from a successful pclose() before the process has
866 // legitimately exited, or at least before SIGCHLD is thrown...the signal may
867 // come quite some time after pclose returns! This causes havoc with later
868 // parts of CMake that expect to catch the signal from other child processes,
869 // so we explicitly wait to catch it here. This should be safe to do with
870 // popen() so long as we don't actually collect the zombie process ourselves.
871 #ifdef __BEOS__
872 #include <signal.h>
873 #undef SIGBUS // this is the same as SIGSEGV on BeOS and causes issues below.
874 static volatile bool beos_seen_signal = false;
875 static void beos_popen_workaround(int sig)
877 beos_seen_signal = true;
879 #endif
881 bool RunCommandViaPopen(const char* command,
882 const char* dir,
883 std::string& output,
884 int& retVal,
885 bool verbose,
886 int /*timeout*/)
888 // if only popen worked on windows.....
889 std::string commandInDir;
890 if(dir)
892 commandInDir = "cd \"";
893 commandInDir += dir;
894 commandInDir += "\" && ";
895 commandInDir += command;
897 else
899 commandInDir = command;
901 commandInDir += " 2>&1";
902 command = commandInDir.c_str();
903 const int BUFFER_SIZE = 4096;
904 char buffer[BUFFER_SIZE];
905 if(verbose)
907 cmSystemTools::Stdout("running ");
908 cmSystemTools::Stdout(command);
909 cmSystemTools::Stdout("\n");
911 fflush(stdout);
912 fflush(stderr);
914 #ifdef __BEOS__
915 beos_seen_signal = false;
916 signal(SIGCHLD, beos_popen_workaround);
917 #endif
919 FILE* cpipe = popen(command, "r");
920 if(!cpipe)
922 #ifdef __BEOS__
923 signal(SIGCHLD, SIG_DFL);
924 #endif
925 return false;
927 fgets(buffer, BUFFER_SIZE, cpipe);
928 while(!feof(cpipe))
930 if(verbose)
932 cmSystemTools::Stdout(buffer);
934 output += buffer;
935 buffer[0] = 0;
936 fgets(buffer, BUFFER_SIZE, cpipe);
939 retVal = pclose(cpipe);
941 #ifdef __BEOS__
942 for (int i = 0; (!beos_seen_signal) && (i < 3); i++)
944 ::sleep(1); // signals should interrupt this...
947 if (!beos_seen_signal)
949 signal(SIGCHLD, SIG_DFL); // oh well, didn't happen. Go on anyhow.
951 #endif
953 if (WIFEXITED(retVal))
955 retVal = WEXITSTATUS(retVal);
956 return true;
958 if (WIFSIGNALED(retVal))
960 retVal = WTERMSIG(retVal);
961 cmOStringStream error;
962 error << "\nProcess terminated due to ";
963 switch (retVal)
965 #ifdef SIGKILL
966 case SIGKILL:
967 error << "SIGKILL";
968 break;
969 #endif
970 #ifdef SIGFPE
971 case SIGFPE:
972 error << "SIGFPE";
973 break;
974 #endif
975 #ifndef __HAIKU__
976 #ifdef SIGBUS
977 case SIGBUS:
978 error << "SIGBUS";
979 break;
980 #endif
981 #endif
982 #ifdef SIGSEGV
983 case SIGSEGV:
984 error << "SIGSEGV";
985 break;
986 #endif
987 default:
988 error << "signal " << retVal;
989 break;
991 output += error.str();
993 return false;
996 #endif // endif WIN32 not CYGWIN
999 // run a command unix uses popen (easy)
1000 // windows uses system and ShortPath
1001 bool cmSystemTools::RunCommand(const char* command,
1002 std::string& output,
1003 int &retVal,
1004 const char* dir,
1005 bool verbose,
1006 int timeout)
1008 if(s_DisableRunCommandOutput)
1010 verbose = false;
1013 #if defined(WIN32) && !defined(__CYGWIN__)
1014 // if the command does not start with a quote, then
1015 // try to find the program, and if the program can not be
1016 // found use system to run the command as it must be a built in
1017 // shell command like echo or dir
1018 int count = 0;
1019 if(command[0] == '\"')
1021 // count the number of quotes
1022 for(const char* s = command; *s != 0; ++s)
1024 if(*s == '\"')
1026 count++;
1027 if(count > 2)
1029 break;
1033 // if there are more than two double quotes use
1034 // GetShortPathName, the cmd.exe program in windows which
1035 // is used by system fails to execute if there are more than
1036 // one set of quotes in the arguments
1037 if(count > 2)
1039 cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
1040 if(quoted.find(command))
1042 std::string shortCmd;
1043 std::string cmd = quoted.match(1);
1044 std::string args = quoted.match(2);
1045 if(! cmSystemTools::FileExists(cmd.c_str()) )
1047 shortCmd = cmd;
1049 else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd))
1051 cmSystemTools::Error("GetShortPath failed for " , cmd.c_str());
1052 return false;
1054 shortCmd += " ";
1055 shortCmd += args;
1057 //return RunCommandViaSystem(shortCmd.c_str(), dir,
1058 // output, retVal, verbose);
1059 //return WindowsRunCommand(shortCmd.c_str(), dir,
1060 //output, retVal, verbose);
1061 return RunCommandViaWin32(shortCmd.c_str(), dir,
1062 output, retVal, verbose, timeout);
1064 else
1066 cmSystemTools::Error("Could not parse command line with quotes ",
1067 command);
1071 // if there is only one set of quotes or no quotes then just run the command
1072 //return RunCommandViaSystem(command, dir, output, retVal, verbose);
1073 //return WindowsRunCommand(command, dir, output, retVal, verbose);
1074 return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout);
1075 #else
1076 return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout);
1077 #endif
1080 bool cmSystemTools::DoesFileExistWithExtensions(
1081 const char* name,
1082 const std::vector<std::string>& headerExts)
1084 std::string hname;
1086 for( std::vector<std::string>::const_iterator ext = headerExts.begin();
1087 ext != headerExts.end(); ++ext )
1089 hname = name;
1090 hname += ".";
1091 hname += *ext;
1092 if(cmSystemTools::FileExists(hname.c_str()))
1094 return true;
1097 return false;
1100 bool cmSystemTools::cmCopyFile(const char* source, const char* destination)
1102 return Superclass::CopyFileAlways(source, destination);
1105 bool cmSystemTools::CopyFileIfDifferent(const char* source,
1106 const char* destination)
1108 return Superclass::CopyFileIfDifferent(source, destination);
1111 bool cmSystemTools::ComputeFileMD5(const char* source, char* md5out)
1113 #if defined(CMAKE_BUILD_WITH_CMAKE)
1114 if(!cmSystemTools::FileExists(source))
1116 return false;
1119 // Open files
1120 #if defined(_WIN32) || defined(__CYGWIN__)
1121 cmsys_ios::ifstream fin(source, cmsys_ios::ios::binary | cmsys_ios::ios::in);
1122 #else
1123 cmsys_ios::ifstream fin(source);
1124 #endif
1125 if(!fin)
1127 return false;
1130 cmsysMD5* md5 = cmsysMD5_New();
1131 cmsysMD5_Initialize(md5);
1133 // Should be efficient enough on most system:
1134 const int bufferSize = 4096;
1135 char buffer[bufferSize];
1136 // This copy loop is very sensitive on certain platforms with
1137 // slightly broken stream libraries (like HPUX). Normally, it is
1138 // incorrect to not check the error condition on the fin.read()
1139 // before using the data, but the fin.gcount() will be zero if an
1140 // error occurred. Therefore, the loop should be safe everywhere.
1141 while(fin)
1143 fin.read(buffer, bufferSize);
1144 if(fin.gcount())
1146 cmsysMD5_Append(md5, reinterpret_cast<unsigned char const*>(buffer),
1147 fin.gcount());
1150 cmsysMD5_FinalizeHex(md5, md5out);
1151 cmsysMD5_Delete(md5);
1153 fin.close();
1154 return true;
1155 #else
1156 (void)source;
1157 (void)md5out;
1158 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1159 return false;
1160 #endif
1163 std::string cmSystemTools::ComputeStringMD5(const char* input)
1165 #if defined(CMAKE_BUILD_WITH_CMAKE)
1166 char md5out[32];
1167 cmsysMD5* md5 = cmsysMD5_New();
1168 cmsysMD5_Initialize(md5);
1169 cmsysMD5_Append(md5, reinterpret_cast<unsigned char const*>(input), -1);
1170 cmsysMD5_FinalizeHex(md5, md5out);
1171 cmsysMD5_Delete(md5);
1172 return std::string(md5out, 32);
1173 #else
1174 (void)input;
1175 cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1176 return "";
1177 #endif
1180 void cmSystemTools::Glob(const char *directory, const char *regexp,
1181 std::vector<std::string>& files)
1183 cmsys::Directory d;
1184 cmsys::RegularExpression reg(regexp);
1186 if (d.Load(directory))
1188 size_t numf;
1189 unsigned int i;
1190 numf = d.GetNumberOfFiles();
1191 for (i = 0; i < numf; i++)
1193 std::string fname = d.GetFile(i);
1194 if (reg.find(fname))
1196 files.push_back(fname);
1203 void cmSystemTools::GlobDirs(const char *fullPath,
1204 std::vector<std::string>& files)
1206 std::string path = fullPath;
1207 std::string::size_type pos = path.find("/*");
1208 if(pos == std::string::npos)
1210 files.push_back(fullPath);
1211 return;
1213 std::string startPath = path.substr(0, pos);
1214 std::string finishPath = path.substr(pos+2);
1216 cmsys::Directory d;
1217 if (d.Load(startPath.c_str()))
1219 for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
1221 if((std::string(d.GetFile(i)) != ".")
1222 && (std::string(d.GetFile(i)) != ".."))
1224 std::string fname = startPath;
1225 fname +="/";
1226 fname += d.GetFile(i);
1227 if(cmSystemTools::FileIsDirectory(fname.c_str()))
1229 fname += finishPath;
1230 cmSystemTools::GlobDirs(fname.c_str(), files);
1238 void cmSystemTools::ExpandList(std::vector<std::string> const& arguments,
1239 std::vector<std::string>& newargs)
1241 std::vector<std::string>::const_iterator i;
1242 for(i = arguments.begin();i != arguments.end(); ++i)
1244 cmSystemTools::ExpandListArgument(*i, newargs);
1248 void cmSystemTools::ExpandListArgument(const std::string& arg,
1249 std::vector<std::string>& newargs,
1250 bool emptyArgs)
1252 // If argument is empty, it is an empty list.
1253 if(arg.length() == 0 && !emptyArgs)
1255 return;
1257 // if there are no ; in the name then just copy the current string
1258 if(arg.find(';') == std::string::npos)
1260 newargs.push_back(arg);
1261 return;
1263 std::vector<char> newArgVec;
1264 // Break the string at non-escaped semicolons not nested in [].
1265 int squareNesting = 0;
1266 for(const char* c = arg.c_str(); *c; ++c)
1268 switch(*c)
1270 case '\\':
1272 // We only want to allow escaping of semicolons. Other
1273 // escapes should not be processed here.
1274 ++c;
1275 if(*c == ';')
1277 newArgVec.push_back(*c);
1279 else
1281 newArgVec.push_back('\\');
1282 if(*c)
1284 newArgVec.push_back(*c);
1286 else
1288 // Terminate the loop properly.
1289 --c;
1292 } break;
1293 case '[':
1295 ++squareNesting;
1296 newArgVec.push_back(*c);
1297 } break;
1298 case ']':
1300 --squareNesting;
1301 newArgVec.push_back(*c);
1302 } break;
1303 case ';':
1305 // Break the string here if we are not nested inside square
1306 // brackets.
1307 if(squareNesting == 0)
1309 if ( newArgVec.size() || emptyArgs )
1311 // Add the last argument if the string is not empty.
1312 newArgVec.push_back(0);
1313 newargs.push_back(&*newArgVec.begin());
1314 newArgVec.clear();
1317 else
1319 newArgVec.push_back(*c);
1321 } break;
1322 default:
1324 // Just append this character.
1325 newArgVec.push_back(*c);
1326 } break;
1329 if ( newArgVec.size() || emptyArgs )
1331 // Add the last argument if the string is not empty.
1332 newArgVec.push_back(0);
1333 newargs.push_back(&*newArgVec.begin());
1337 bool cmSystemTools::SimpleGlob(const cmStdString& glob,
1338 std::vector<cmStdString>& files,
1339 int type /* = 0 */)
1341 files.clear();
1342 if ( glob[glob.size()-1] != '*' )
1344 return false;
1346 std::string path = cmSystemTools::GetFilenamePath(glob);
1347 std::string ppath = cmSystemTools::GetFilenameName(glob);
1348 ppath = ppath.substr(0, ppath.size()-1);
1349 if ( path.size() == 0 )
1351 path = "/";
1354 bool res = false;
1355 cmsys::Directory d;
1356 if (d.Load(path.c_str()))
1358 for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
1360 if((std::string(d.GetFile(i)) != ".")
1361 && (std::string(d.GetFile(i)) != ".."))
1363 std::string fname = path;
1364 if ( path[path.size()-1] != '/' )
1366 fname +="/";
1368 fname += d.GetFile(i);
1369 std::string sfname = d.GetFile(i);
1370 if ( type > 0 && cmSystemTools::FileIsDirectory(fname.c_str()) )
1372 continue;
1374 if ( type < 0 && !cmSystemTools::FileIsDirectory(fname.c_str()) )
1376 continue;
1378 if ( sfname.size() >= ppath.size() &&
1379 sfname.substr(0, ppath.size()) ==
1380 ppath )
1382 files.push_back(fname);
1383 res = true;
1388 return res;
1391 cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext)
1393 if ( ! cext || *cext == 0 )
1395 return cmSystemTools::NO_FILE_FORMAT;
1397 //std::string ext = cmSystemTools::LowerCase(cext);
1398 std::string ext = cext;
1399 if ( ext == "c" || ext == ".c" ||
1400 ext == "m" || ext == ".m"
1401 ) { return cmSystemTools::C_FILE_FORMAT; }
1402 if (
1403 ext == "C" || ext == ".C" ||
1404 ext == "M" || ext == ".M" ||
1405 ext == "c++" || ext == ".c++" ||
1406 ext == "cc" || ext == ".cc" ||
1407 ext == "cpp" || ext == ".cpp" ||
1408 ext == "cxx" || ext == ".cxx" ||
1409 ext == "mm" || ext == ".mm"
1410 ) { return cmSystemTools::CXX_FILE_FORMAT; }
1411 if (
1412 ext == "f" || ext == ".f" ||
1413 ext == "F" || ext == ".F" ||
1414 ext == "f77" || ext == ".f77" ||
1415 ext == "f90" || ext == ".f90" ||
1416 ext == "for" || ext == ".for" ||
1417 ext == "f95" || ext == ".f95"
1418 ) { return cmSystemTools::FORTRAN_FILE_FORMAT; }
1419 if ( ext == "java" || ext == ".java" )
1420 { return cmSystemTools::JAVA_FILE_FORMAT; }
1421 if (
1422 ext == "H" || ext == ".H" ||
1423 ext == "h" || ext == ".h" ||
1424 ext == "h++" || ext == ".h++" ||
1425 ext == "hm" || ext == ".hm" ||
1426 ext == "hpp" || ext == ".hpp" ||
1427 ext == "hxx" || ext == ".hxx" ||
1428 ext == "in" || ext == ".in" ||
1429 ext == "txx" || ext == ".txx"
1430 ) { return cmSystemTools::HEADER_FILE_FORMAT; }
1431 if ( ext == "rc" || ext == ".rc" )
1432 { return cmSystemTools::RESOURCE_FILE_FORMAT; }
1433 if ( ext == "def" || ext == ".def" )
1434 { return cmSystemTools::DEFINITION_FILE_FORMAT; }
1435 if ( ext == "lib" || ext == ".lib" ||
1436 ext == "a" || ext == ".a")
1437 { return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT; }
1438 if ( ext == "o" || ext == ".o" ||
1439 ext == "obj" || ext == ".obj")
1440 { return cmSystemTools::OBJECT_FILE_FORMAT; }
1441 #ifdef __APPLE__
1442 if ( ext == "dylib" || ext == ".dylib" )
1443 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; }
1444 if ( ext == "so" || ext == ".so" ||
1445 ext == "bundle" || ext == ".bundle" )
1446 { return cmSystemTools::MODULE_FILE_FORMAT; }
1447 #else // __APPLE__
1448 if ( ext == "so" || ext == ".so" ||
1449 ext == "sl" || ext == ".sl" ||
1450 ext == "dll" || ext == ".dll" )
1451 { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; }
1452 #endif // __APPLE__
1453 return cmSystemTools::UNKNOWN_FILE_FORMAT;
1456 bool cmSystemTools::Split(const char* s, std::vector<cmStdString>& l)
1458 std::vector<std::string> temp;
1459 bool res = Superclass::Split(s, temp);
1460 for(std::vector<std::string>::const_iterator i = temp.begin();
1461 i != temp.end(); ++i)
1463 l.push_back(*i);
1465 return res;
1468 std::string cmSystemTools::ConvertToOutputPath(const char* path)
1470 #if defined(_WIN32) && !defined(__CYGWIN__)
1471 if(s_ForceUnixPaths)
1473 return cmSystemTools::ConvertToUnixOutputPath(path);
1475 return cmSystemTools::ConvertToWindowsOutputPath(path);
1476 #else
1477 return cmSystemTools::ConvertToUnixOutputPath(path);
1478 #endif
1481 void cmSystemTools::ConvertToOutputSlashes(std::string& path)
1483 #if defined(_WIN32) && !defined(__CYGWIN__)
1484 if(!s_ForceUnixPaths)
1486 // Convert to windows slashes.
1487 std::string::size_type pos = 0;
1488 while((pos = path.find('/', pos)) != std::string::npos)
1490 path[pos++] = '\\';
1493 #else
1494 static_cast<void>(path);
1495 #endif
1498 std::string cmSystemTools::ConvertToRunCommandPath(const char* path)
1500 #if defined(_WIN32) && !defined(__CYGWIN__)
1501 return cmSystemTools::ConvertToWindowsOutputPath(path);
1502 #else
1503 return cmSystemTools::ConvertToUnixOutputPath(path);
1504 #endif
1507 bool cmSystemTools::StringEndsWith(const char* str1, const char* str2)
1509 if ( !str1 || !str2 || strlen(str1) < strlen(str2) )
1511 return 0;
1513 return !strncmp(str1 + (strlen(str1)-strlen(str2)), str2, strlen(str2));
1516 // compute the relative path from here to there
1517 std::string cmSystemTools::RelativePath(const char* local, const char* remote)
1519 if(!cmSystemTools::FileIsFullPath(local))
1521 cmSystemTools::Error("RelativePath must be passed a full path to local: ",
1522 local);
1524 if(!cmSystemTools::FileIsFullPath(remote))
1526 cmSystemTools::Error
1527 ("RelativePath must be passed a full path to remote: ", remote);
1529 return cmsys::SystemTools::RelativePath(local, remote);
1532 class cmDeletingCharVector : public std::vector<char*>
1534 public:
1535 ~cmDeletingCharVector()
1537 for(std::vector<char*>::iterator i = this->begin();
1538 i != this->end(); ++i)
1540 delete []*i;
1546 bool cmSystemTools::PutEnv(const char* value)
1548 static cmDeletingCharVector localEnvironment;
1549 char* envVar = new char[strlen(value)+1];
1550 strcpy(envVar, value);
1551 int ret = putenv(envVar);
1552 // save the pointer in the static vector so that it can
1553 // be deleted on exit
1554 localEnvironment.push_back(envVar);
1555 return ret == 0;
1558 #ifdef CMAKE_BUILD_WITH_CMAKE
1559 //----------------------------------------------------------------------
1560 bool cmSystemTools::UnsetEnv(const char* value)
1562 #if !defined(HAVE_UNSETENV)
1563 std::string var = value;
1564 var += "=";
1565 return cmSystemTools::PutEnv(var.c_str());
1566 #else
1567 unsetenv(value);
1568 return true;
1569 #endif
1572 //----------------------------------------------------------------------
1573 std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
1575 std::vector<std::string> env;
1576 int cc;
1577 for ( cc = 0; environ[cc]; ++ cc )
1579 env.push_back(environ[cc]);
1581 return env;
1584 //----------------------------------------------------------------------
1585 std::vector<std::string> cmSystemTools::AppendEnv(
1586 std::vector<std::string>* env)
1588 std::vector<std::string> origEnv = GetEnvironmentVariables();
1590 if (env && env->size()>0)
1592 std::vector<std::string>::const_iterator eit;
1594 for (eit = env->begin(); eit!= env->end(); ++eit)
1596 PutEnv(eit->c_str());
1600 return origEnv;
1603 //----------------------------------------------------------------------
1604 void cmSystemTools::RestoreEnv(const std::vector<std::string>& env)
1606 std::vector<std::string>::const_iterator eit;
1608 // First clear everything in the current environment:
1610 std::vector<std::string> currentEnv = GetEnvironmentVariables();
1611 for (eit = currentEnv.begin(); eit!= currentEnv.end(); ++eit)
1613 std::string var(*eit);
1615 std::string::size_type pos = var.find("=");
1616 if (pos != std::string::npos)
1618 var = var.substr(0, pos);
1621 UnsetEnv(var.c_str());
1624 // Then put back each entry from the original environment:
1626 for (eit = env.begin(); eit!= env.end(); ++eit)
1628 PutEnv(eit->c_str());
1631 #endif
1633 void cmSystemTools::EnableVSConsoleOutput()
1635 // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
1636 // display output to the console unless this environment variable is
1637 // set. We need it to capture the output of these build tools.
1638 // Note for future work that one could pass "/out \\.\pipe\NAME" to
1639 // either of these executables where NAME is created with
1640 // CreateNamedPipe. This would bypass the internal buffering of the
1641 // output and allow it to be captured on the fly.
1642 #ifdef _WIN32
1643 cmSystemTools::PutEnv("vsconsoleoutput=1");
1644 #endif
1647 bool cmSystemTools::IsPathToFramework(const char* path)
1649 if(cmSystemTools::FileIsFullPath(path))
1651 std::string libname = path;
1652 if(libname.find(".framework") == libname.size()+1-sizeof(".framework"))
1654 return true;
1657 return false;
1660 #if defined(CMAKE_BUILD_WITH_CMAKE)
1661 struct cmSystemToolsGZStruct
1663 gzFile GZFile;
1666 extern "C" {
1667 int cmSystemToolsGZStructOpen(void* call_data, const char *pathname,
1668 int oflags, mode_t mode);
1669 int cmSystemToolsGZStructClose(void* call_data);
1670 ssize_t cmSystemToolsGZStructRead(void* call_data, void* buf, size_t count);
1671 ssize_t cmSystemToolsGZStructWrite(void* call_data, const void* buf,
1672 size_t count);
1675 int cmSystemToolsGZStructOpen(void* call_data, const char *pathname,
1676 int oflags, mode_t mode)
1678 const char *gzoflags;
1679 int fd;
1681 cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data);
1683 switch (oflags & O_ACCMODE)
1685 case O_WRONLY:
1686 gzoflags = "wb";
1687 break;
1688 case O_RDONLY:
1689 gzoflags = "rb";
1690 break;
1691 default:
1692 case O_RDWR:
1693 errno = EINVAL;
1694 return -1;
1697 fd = open(pathname, oflags, mode);
1698 if (fd == -1)
1700 return -1;
1703 // no fchmod on BeOS 5...do pathname instead.
1704 #if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
1705 if ((oflags & O_CREAT) && chmod(pathname, mode))
1707 return -1;
1709 #elif !defined(_WIN32) || defined(__CYGWIN__)
1710 if ((oflags & O_CREAT) && fchmod(fd, mode))
1712 return -1;
1714 #endif
1716 gzf->GZFile = gzdopen(fd, gzoflags);
1717 if (!gzf->GZFile)
1719 errno = ENOMEM;
1720 return -1;
1723 return fd;
1726 int cmSystemToolsGZStructClose(void* call_data)
1728 cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data);
1729 return gzclose(gzf->GZFile);
1732 ssize_t cmSystemToolsGZStructRead(void* call_data, void* buf, size_t count)
1734 cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data);
1735 return gzread(gzf->GZFile, buf, static_cast<int>(count));
1738 ssize_t cmSystemToolsGZStructWrite(void* call_data, const void* buf,
1739 size_t count)
1741 cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data);
1742 return gzwrite(gzf->GZFile, (void*)buf, static_cast<int>(count));
1745 #endif
1747 bool cmSystemTools::CreateTar(const char* outFileName,
1748 const std::vector<cmStdString>& files,
1749 bool gzip, bool verbose)
1751 #if defined(CMAKE_BUILD_WITH_CMAKE)
1752 TAR *t;
1753 char buf[TAR_MAXPATHLEN];
1754 char pathname[TAR_MAXPATHLEN];
1755 cmSystemToolsGZStruct gzs;
1757 tartype_t gztype = {
1758 (openfunc_t)cmSystemToolsGZStructOpen,
1759 (closefunc_t)cmSystemToolsGZStructClose,
1760 (readfunc_t)cmSystemToolsGZStructRead,
1761 (writefunc_t)cmSystemToolsGZStructWrite,
1762 &gzs
1765 // Ok, this libtar is not const safe. for now use auto_ptr hack
1766 char* realName = new char[ strlen(outFileName) + 1 ];
1767 std::auto_ptr<char> realNamePtr(realName);
1768 strcpy(realName, outFileName);
1769 int options = 0;
1770 if(verbose)
1772 options |= TAR_VERBOSE;
1774 #ifdef __CYGWIN__
1775 options |= TAR_GNU;
1776 #endif
1777 if (tar_open(&t, realName,
1778 (gzip? &gztype : NULL),
1779 O_WRONLY | O_CREAT, 0644,
1780 options) == -1)
1782 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno));
1783 return false;
1786 std::vector<cmStdString>::const_iterator it;
1787 for (it = files.begin(); it != files.end(); ++ it )
1789 strncpy(pathname, it->c_str(), sizeof(pathname));
1790 pathname[sizeof(pathname)-1] = 0;
1791 strncpy(buf, pathname, sizeof(buf));
1792 buf[sizeof(buf)-1] = 0;
1793 if (tar_append_tree(t, buf, pathname) != 0)
1795 cmOStringStream ostr;
1796 ostr << "Problem with tar_append_tree(\"" << buf << "\", \""
1797 << pathname << "\"): "
1798 << strerror(errno);
1799 cmSystemTools::Error(ostr.str().c_str());
1800 tar_close(t);
1801 return false;
1805 if (tar_append_eof(t) != 0)
1807 cmSystemTools::Error("Problem with tar_append_eof(): ", strerror(errno));
1808 tar_close(t);
1809 return false;
1812 if (tar_close(t) != 0)
1814 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno));
1815 return false;
1817 return true;
1818 #else
1819 (void)outFileName;
1820 (void)files;
1821 (void)gzip;
1822 (void)verbose;
1823 return false;
1824 #endif
1827 bool cmSystemTools::ExtractTar(const char* outFileName,
1828 const std::vector<cmStdString>& files,
1829 bool gzip, bool verbose)
1831 (void)files;
1832 #if defined(CMAKE_BUILD_WITH_CMAKE)
1833 TAR *t;
1834 cmSystemToolsGZStruct gzs;
1836 tartype_t gztype = {
1837 cmSystemToolsGZStructOpen,
1838 cmSystemToolsGZStructClose,
1839 cmSystemToolsGZStructRead,
1840 cmSystemToolsGZStructWrite,
1841 &gzs
1844 // Ok, this libtar is not const safe. for now use auto_ptr hack
1845 char* realName = new char[ strlen(outFileName) + 1 ];
1846 std::auto_ptr<char> realNamePtr(realName);
1847 strcpy(realName, outFileName);
1848 if (tar_open(&t, realName,
1849 (gzip? &gztype : NULL),
1850 O_RDONLY
1851 #ifdef _WIN32
1852 | O_BINARY
1853 #endif
1854 , 0,
1855 (verbose?TAR_VERBOSE:0)
1856 | 0) == -1)
1858 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno));
1859 return false;
1862 if (tar_extract_all(t, 0) != 0)
1864 cmSystemTools::Error("Problem with tar_extract_all(): ", strerror(errno));
1865 return false;
1868 if (tar_close(t) != 0)
1870 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno));
1871 return false;
1873 return true;
1874 #else
1875 (void)outFileName;
1876 (void)gzip;
1877 (void)verbose;
1878 return false;
1879 #endif
1882 bool cmSystemTools::ListTar(const char* outFileName,
1883 std::vector<cmStdString>& files, bool gzip,
1884 bool verbose)
1886 #if defined(CMAKE_BUILD_WITH_CMAKE)
1887 TAR *t;
1888 cmSystemToolsGZStruct gzs;
1890 tartype_t gztype = {
1891 cmSystemToolsGZStructOpen,
1892 cmSystemToolsGZStructClose,
1893 cmSystemToolsGZStructRead,
1894 cmSystemToolsGZStructWrite,
1895 &gzs
1898 // Ok, this libtar is not const safe. for now use auto_ptr hack
1899 char* realName = new char[ strlen(outFileName) + 1 ];
1900 std::auto_ptr<char> realNamePtr(realName);
1901 strcpy(realName, outFileName);
1902 if (tar_open(&t, realName,
1903 (gzip? &gztype : NULL),
1904 O_RDONLY
1905 #ifdef _WIN32
1906 | O_BINARY
1907 #endif
1908 , 0,
1909 (verbose?TAR_VERBOSE:0)
1910 | 0) == -1)
1912 cmSystemTools::Error("Problem with tar_open(): ", strerror(errno));
1913 return false;
1916 while ((th_read(t)) == 0)
1918 const char* filename = th_get_pathname(t);
1919 files.push_back(filename);
1921 if ( verbose )
1923 th_print_long_ls(t);
1925 else
1927 std::cout << filename << std::endl;
1930 #ifdef DEBUG
1931 th_print(t);
1932 #endif
1933 if (TH_ISREG(t) && tar_skip_regfile(t) != 0)
1935 cmSystemTools::Error("Problem with tar_skip_regfile(): ",
1936 strerror(errno));
1937 return false;
1941 if (tar_close(t) != 0)
1943 cmSystemTools::Error("Problem with tar_close(): ", strerror(errno));
1944 return false;
1946 return true;
1947 #else
1948 (void)outFileName;
1949 (void)files;
1950 (void)gzip;
1951 (void)verbose;
1952 return false;
1953 #endif
1956 int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
1957 double timeout,
1958 std::vector<char>& out,
1959 std::vector<char>& err)
1961 line = "";
1962 std::vector<char>::iterator outiter = out.begin();
1963 std::vector<char>::iterator erriter = err.begin();
1964 while(1)
1966 // Check for a newline in stdout.
1967 for(;outiter != out.end(); ++outiter)
1969 if((*outiter == '\r') && ((outiter+1) == out.end()))
1971 break;
1973 else if(*outiter == '\n' || *outiter == '\0')
1975 int length = outiter-out.begin();
1976 if(length > 1 && *(outiter-1) == '\r')
1978 --length;
1980 if(length > 0)
1982 line.append(&out[0], length);
1984 out.erase(out.begin(), outiter+1);
1985 return cmsysProcess_Pipe_STDOUT;
1989 // Check for a newline in stderr.
1990 for(;erriter != err.end(); ++erriter)
1992 if((*erriter == '\r') && ((erriter+1) == err.end()))
1994 break;
1996 else if(*erriter == '\n' || *erriter == '\0')
1998 int length = erriter-err.begin();
1999 if(length > 1 && *(erriter-1) == '\r')
2001 --length;
2003 if(length > 0)
2005 line.append(&err[0], length);
2007 err.erase(err.begin(), erriter+1);
2008 return cmsysProcess_Pipe_STDERR;
2012 // No newlines found. Wait for more data from the process.
2013 int length;
2014 char* data;
2015 int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
2016 if(pipe == cmsysProcess_Pipe_Timeout)
2018 // Timeout has been exceeded.
2019 return pipe;
2021 else if(pipe == cmsysProcess_Pipe_STDOUT)
2023 // Append to the stdout buffer.
2024 std::vector<char>::size_type size = out.size();
2025 out.insert(out.end(), data, data+length);
2026 outiter = out.begin()+size;
2028 else if(pipe == cmsysProcess_Pipe_STDERR)
2030 // Append to the stderr buffer.
2031 std::vector<char>::size_type size = err.size();
2032 err.insert(err.end(), data, data+length);
2033 erriter = err.begin()+size;
2035 else if(pipe == cmsysProcess_Pipe_None)
2037 // Both stdout and stderr pipes have broken. Return leftover data.
2038 if(!out.empty())
2040 line.append(&out[0], outiter-out.begin());
2041 out.erase(out.begin(), out.end());
2042 return cmsysProcess_Pipe_STDOUT;
2044 else if(!err.empty())
2046 line.append(&err[0], erriter-err.begin());
2047 err.erase(err.begin(), err.end());
2048 return cmsysProcess_Pipe_STDERR;
2050 else
2052 return cmsysProcess_Pipe_None;
2058 void cmSystemTools::DoNotInheritStdPipes()
2060 #ifdef _WIN32
2061 // Check to see if we are attached to a console
2062 // if so, then do not stop the inherited pipes
2063 // or stdout and stderr will not show up in dos
2064 // shell windows
2065 CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
2066 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
2067 if(GetConsoleScreenBufferInfo(hOut, &hOutInfo))
2069 return;
2072 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
2073 DuplicateHandle(GetCurrentProcess(), out,
2074 GetCurrentProcess(), &out, 0, FALSE,
2075 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2076 SetStdHandle(STD_OUTPUT_HANDLE, out);
2079 HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
2080 DuplicateHandle(GetCurrentProcess(), out,
2081 GetCurrentProcess(), &out, 0, FALSE,
2082 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2083 SetStdHandle(STD_ERROR_HANDLE, out);
2085 #endif
2088 //----------------------------------------------------------------------------
2089 bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
2091 #if defined(_WIN32) && !defined(__CYGWIN__)
2092 cmSystemToolsWindowsHandle hFrom =
2093 CreateFile(fromFile, GENERIC_READ, FILE_SHARE_READ, 0,
2094 OPEN_EXISTING, 0, 0);
2095 cmSystemToolsWindowsHandle hTo =
2096 CreateFile(toFile, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2097 if(!hFrom || !hTo)
2099 return false;
2101 FILETIME timeCreation;
2102 FILETIME timeLastAccess;
2103 FILETIME timeLastWrite;
2104 if(!GetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite))
2106 return false;
2108 if(!SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite))
2110 return false;
2112 #else
2113 struct stat fromStat;
2114 if(stat(fromFile, &fromStat) < 0)
2116 return false;
2119 struct utimbuf buf;
2120 buf.actime = fromStat.st_atime;
2121 buf.modtime = fromStat.st_mtime;
2122 if(utime(toFile, &buf) < 0)
2124 return false;
2126 #endif
2127 return true;
2130 //----------------------------------------------------------------------------
2131 cmSystemToolsFileTime* cmSystemTools::FileTimeNew()
2133 return new cmSystemToolsFileTime;
2136 //----------------------------------------------------------------------------
2137 void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime* t)
2139 delete t;
2142 //----------------------------------------------------------------------------
2143 bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
2145 #if defined(_WIN32) && !defined(__CYGWIN__)
2146 cmSystemToolsWindowsHandle h =
2147 CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
2148 if(!h)
2150 return false;
2152 if(!GetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2154 return false;
2156 #else
2157 struct stat st;
2158 if(stat(fname, &st) < 0)
2160 return false;
2162 t->timeBuf.actime = st.st_atime;
2163 t->timeBuf.modtime = st.st_mtime;
2164 #endif
2165 return true;
2168 //----------------------------------------------------------------------------
2169 bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
2171 #if defined(_WIN32) && !defined(__CYGWIN__)
2172 cmSystemToolsWindowsHandle h =
2173 CreateFile(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2174 if(!h)
2176 return false;
2178 if(!SetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2180 return false;
2182 #else
2183 if(utime(fname, &t->timeBuf) < 0)
2185 return false;
2187 #endif
2188 return true;
2191 //----------------------------------------------------------------------------
2192 static std::string cmSystemToolsExecutableDirectory;
2193 void cmSystemTools::FindExecutableDirectory(const char* argv0)
2195 #if defined(_WIN32) && !defined(__CYGWIN__)
2196 (void)argv0; // ignore this on windows
2197 char modulepath[_MAX_PATH];
2198 ::GetModuleFileName(NULL, modulepath, sizeof(modulepath));
2199 cmSystemToolsExecutableDirectory =
2200 cmSystemTools::GetFilenamePath(modulepath);
2201 return;
2202 #else
2203 std::string errorMsg;
2204 std::string exe;
2205 if(cmSystemTools::FindProgramPath(argv0, exe, errorMsg))
2207 // remove symlinks
2208 exe = cmSystemTools::GetRealPath(exe.c_str());
2209 cmSystemToolsExecutableDirectory =
2210 cmSystemTools::GetFilenamePath(exe.c_str());
2212 else
2214 // ???
2216 #endif
2219 //----------------------------------------------------------------------------
2220 const char* cmSystemTools::GetExecutableDirectory()
2222 return cmSystemToolsExecutableDirectory.c_str();
2225 //----------------------------------------------------------------------------
2226 #if defined(CMAKE_BUILD_WITH_CMAKE)
2227 void cmSystemTools::MakefileColorEcho(int color, const char* message,
2228 bool newline, bool enabled)
2230 // On some platforms (an MSYS prompt) cmsysTerminal may not be able
2231 // to determine whether the stream is displayed on a tty. In this
2232 // case it assumes no unless we tell it otherwise. Since we want
2233 // color messages to be displayed for users we will assume yes.
2234 // However, we can test for some situations when the answer is most
2235 // likely no.
2236 int assumeTTY = cmsysTerminal_Color_AssumeTTY;
2237 if(cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
2238 cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
2239 cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE"))
2241 // Avoid printing color escapes during dashboard builds.
2242 assumeTTY = 0;
2245 if(enabled)
2247 cmsysTerminal_cfprintf(color | assumeTTY, stdout, "%s%s",
2248 message, newline? "\n" : "");
2250 else
2252 // Color is disabled. Print without color.
2253 fprintf(stdout, "%s%s", message, newline? "\n" : "");
2256 #endif
2258 //----------------------------------------------------------------------------
2259 bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
2260 std::string& soname)
2262 // For ELF shared libraries use a real parser to get the correct
2263 // soname.
2264 #if defined(CMAKE_USE_ELF_PARSER)
2265 cmELF elf(fullPath.c_str());
2266 if(elf)
2268 return elf.GetSOName(soname);
2270 #endif
2272 // If the file is not a symlink we have no guess for its soname.
2273 if(!cmSystemTools::FileIsSymlink(fullPath.c_str()))
2275 return false;
2277 if(!cmSystemTools::ReadSymlink(fullPath.c_str(), soname))
2279 return false;
2282 // If the symlink has a path component we have no guess for the soname.
2283 if(!cmSystemTools::GetFilenamePath(soname).empty())
2285 return false;
2288 // If the symlink points at an extended version of the same name
2289 // assume it is the soname.
2290 std::string name = cmSystemTools::GetFilenameName(fullPath);
2291 if(soname.length() > name.length() &&
2292 soname.substr(0, name.length()) == name)
2294 return true;
2296 return false;
2299 //----------------------------------------------------------------------------
2300 #if defined(CMAKE_USE_ELF_PARSER)
2301 std::string::size_type cmSystemToolsFindRPath(std::string const& have,
2302 std::string const& want)
2304 // Search for the desired rpath.
2305 std::string::size_type pos = have.find(want);
2307 // If the path is not present we are done.
2308 if(pos == std::string::npos)
2310 return pos;
2313 // Build a regex to match a properly separated path instance.
2314 std::string regex_str = "(^|:)(";
2315 for(std::string::const_iterator i = want.begin(); i != want.end(); ++i)
2317 int ch = *i;
2318 if(!(('a' <= ch && ch <= 'z') ||
2319 ('A' <= ch && ch <= 'Z') ||
2320 ('0' <= ch && ch <= '9')))
2322 // Escape the non-alphanumeric character.
2323 regex_str += "\\";
2325 // Store the character.
2326 regex_str.append(1, static_cast<char>(ch));
2328 regex_str += ")(:|$)";
2330 // Look for the separated path.
2331 cmsys::RegularExpression regex(regex_str.c_str());
2332 if(regex.find(have))
2334 // Return the position of the path portion.
2335 return regex.start(2);
2337 else
2339 // The desired rpath was not found.
2340 return std::string::npos;
2343 #endif
2345 #if defined(CMAKE_USE_ELF_PARSER)
2346 struct cmSystemToolsRPathInfo
2348 unsigned long Position;
2349 unsigned long Size;
2350 std::string Name;
2351 std::string Value;
2353 #endif
2355 //----------------------------------------------------------------------------
2356 bool cmSystemTools::ChangeRPath(std::string const& file,
2357 std::string const& oldRPath,
2358 std::string const& newRPath,
2359 std::string* emsg,
2360 bool* changed)
2362 #if defined(CMAKE_USE_ELF_PARSER)
2363 if(changed)
2365 *changed = false;
2367 int rp_count = 0;
2368 cmSystemToolsRPathInfo rp[2];
2370 // Parse the ELF binary.
2371 cmELF elf(file.c_str());
2373 // Get the RPATH and RUNPATH entries from it.
2374 int se_count = 0;
2375 cmELF::StringEntry const* se[2] = {0, 0};
2376 const char* se_name[2] = {0, 0};
2377 if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2379 se[se_count] = se_rpath;
2380 se_name[se_count] = "RPATH";
2381 ++se_count;
2383 if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2385 se[se_count] = se_runpath;
2386 se_name[se_count] = "RUNPATH";
2387 ++se_count;
2389 if(se_count == 0)
2391 if(newRPath.empty())
2393 // The new rpath is empty and there is no rpath anyway so it is
2394 // okay.
2395 return true;
2397 else
2399 if(emsg)
2401 *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
2402 *emsg += elf.GetErrorMessage();
2404 return false;
2408 for(int i=0; i < se_count; ++i)
2410 // If both RPATH and RUNPATH refer to the same string literal it
2411 // needs to be changed only once.
2412 if(rp_count && rp[0].Position == se[i]->Position)
2414 continue;
2417 // Make sure the current rpath contains the old rpath.
2418 std::string::size_type pos =
2419 cmSystemToolsFindRPath(se[i]->Value, oldRPath);
2420 if(pos == std::string::npos)
2422 // If it contains the new rpath instead then it is okay.
2423 if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
2425 continue;
2427 if(emsg)
2429 cmOStringStream e;
2430 e << "The current " << se_name[i] << " is:\n"
2431 << " " << se[i]->Value << "\n"
2432 << "which does not contain:\n"
2433 << " " << oldRPath << "\n"
2434 << "as was expected.";
2435 *emsg = e.str();
2437 return false;
2440 // Store information about the entry in the file.
2441 rp[rp_count].Position = se[i]->Position;
2442 rp[rp_count].Size = se[i]->Size;
2443 rp[rp_count].Name = se_name[i];
2445 // Construct the new value which preserves the part of the path
2446 // not being changed.
2447 rp[rp_count].Value = se[i]->Value.substr(0, pos);
2448 rp[rp_count].Value += newRPath;
2449 rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
2450 oldRPath.npos);
2452 // Make sure there is enough room to store the new rpath and at
2453 // least one null terminator.
2454 if(rp[rp_count].Size < rp[rp_count].Value.length()+1)
2456 if(emsg)
2458 *emsg = "The replacement path is too long for the ";
2459 *emsg += se_name[i];
2460 *emsg += " entry.";
2462 return false;
2465 // This entry is ready for update.
2466 ++rp_count;
2470 // If no runtime path needs to be changed, we are done.
2471 if(rp_count == 0)
2473 return true;
2477 // Open the file for update.
2478 std::ofstream f(file.c_str(),
2479 std::ios::in | std::ios::out | std::ios::binary);
2480 if(!f)
2482 if(emsg)
2484 *emsg = "Error opening file for update.";
2486 return false;
2489 // Store the new RPATH and RUNPATH strings.
2490 for(int i=0; i < rp_count; ++i)
2492 // Seek to the RPATH position.
2493 if(!f.seekp(rp[i].Position))
2495 if(emsg)
2497 *emsg = "Error seeking to ";
2498 *emsg += rp[i].Name;
2499 *emsg += " position.";
2501 return false;
2504 // Write the new rpath. Follow it with enough null terminators to
2505 // fill the string table entry.
2506 f << rp[i].Value;
2507 for(unsigned long j=rp[i].Value.length(); j < rp[i].Size; ++j)
2509 f << '\0';
2512 // Make sure it wrote correctly.
2513 if(!f)
2515 if(emsg)
2517 *emsg = "Error writing the new ";
2518 *emsg += rp[i].Name;
2519 *emsg += " string to the file.";
2521 return false;
2526 // Everything was updated successfully.
2527 if(changed)
2529 *changed = true;
2531 return true;
2532 #else
2533 (void)file;
2534 (void)oldRPath;
2535 (void)newRPath;
2536 (void)emsg;
2537 (void)changed;
2538 return false;
2539 #endif
2542 //----------------------------------------------------------------------------
2543 bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
2544 bool* removed)
2546 #if defined(CMAKE_USE_ELF_PARSER)
2547 if(removed)
2549 *removed = false;
2551 int zeroCount = 0;
2552 unsigned long zeroPosition[2] = {0,0};
2553 unsigned long zeroSize[2] = {0,0};
2554 unsigned long bytesBegin = 0;
2555 std::vector<char> bytes;
2557 // Parse the ELF binary.
2558 cmELF elf(file.c_str());
2560 // Get the RPATH and RUNPATH entries from it and sort them by index
2561 // in the dynamic section header.
2562 int se_count = 0;
2563 cmELF::StringEntry const* se[2] = {0, 0};
2564 if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2566 se[se_count++] = se_rpath;
2568 if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2570 se[se_count++] = se_runpath;
2572 if(se_count == 0)
2574 // There is no RPATH or RUNPATH anyway.
2575 return true;
2577 if(se_count == 2 && se[1]->IndexInSection < se[0]->IndexInSection)
2579 cmsys_stl::swap(se[0], se[1]);
2582 // Get the size of the dynamic section header.
2583 unsigned int count = elf.GetDynamicEntryCount();
2584 if(count == 0)
2586 // This should happen only for invalid ELF files where a DT_NULL
2587 // appears before the end of the table.
2588 if(emsg)
2590 *emsg = "DYNAMIC section contains a DT_NULL before the end.";
2592 return false;
2595 // Save information about the string entries to be zeroed.
2596 zeroCount = se_count;
2597 for(int i=0; i < se_count; ++i)
2599 zeroPosition[i] = se[i]->Position;
2600 zeroSize[i] = se[i]->Size;
2603 // Get the range of file positions corresponding to each entry and
2604 // the rest of the table after them.
2605 unsigned long entryBegin[3] = {0,0,0};
2606 unsigned long entryEnd[2] = {0,0};
2607 for(int i=0; i < se_count; ++i)
2609 entryBegin[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection);
2610 entryEnd[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection+1);
2612 entryBegin[se_count] = elf.GetDynamicEntryPosition(count);
2614 // The data are to be written over the old table entries starting at
2615 // the first one being removed.
2616 bytesBegin = entryBegin[0];
2617 unsigned long bytesEnd = entryBegin[se_count];
2619 // Allocate a buffer to hold the part of the file to be written.
2620 // Initialize it with zeros.
2621 bytes.resize(bytesEnd - bytesBegin, 0);
2623 // Read the part of the DYNAMIC section header that will move.
2624 // The remainder of the buffer will be left with zeros which
2625 // represent a DT_NULL entry.
2626 char* data = &bytes[0];
2627 for(int i=0; i < se_count; ++i)
2629 // Read data between the entries being removed.
2630 unsigned long sz = entryBegin[i+1] - entryEnd[i];
2631 if(sz > 0 && !elf.ReadBytes(entryEnd[i], sz, data))
2633 if(emsg)
2635 *emsg = "Failed to read DYNAMIC section header.";
2637 return false;
2639 data += sz;
2643 // Open the file for update.
2644 std::ofstream f(file.c_str(),
2645 std::ios::in | std::ios::out | std::ios::binary);
2646 if(!f)
2648 if(emsg)
2650 *emsg = "Error opening file for update.";
2652 return false;
2655 // Write the new DYNAMIC table header.
2656 if(!f.seekp(bytesBegin))
2658 if(emsg)
2660 *emsg = "Error seeking to DYNAMIC table header for RPATH.";
2662 return false;
2664 if(!f.write(&bytes[0], bytes.size()))
2666 if(emsg)
2668 *emsg = "Error replacing DYNAMIC table header.";
2670 return false;
2673 // Fill the RPATH and RUNPATH strings with zero bytes.
2674 for(int i=0; i < zeroCount; ++i)
2676 if(!f.seekp(zeroPosition[i]))
2678 if(emsg)
2680 *emsg = "Error seeking to RPATH position.";
2682 return false;
2684 for(unsigned long j=0; j < zeroSize[i]; ++j)
2686 f << '\0';
2688 if(!f)
2690 if(emsg)
2692 *emsg = "Error writing the empty rpath string to the file.";
2694 return false;
2698 // Everything was updated successfully.
2699 if(removed)
2701 *removed = true;
2703 return true;
2704 #else
2705 (void)file;
2706 (void)emsg;
2707 (void)removed;
2708 return false;
2709 #endif
2712 //----------------------------------------------------------------------------
2713 bool cmSystemTools::CheckRPath(std::string const& file,
2714 std::string const& newRPath)
2716 #if defined(CMAKE_USE_ELF_PARSER)
2717 // Parse the ELF binary.
2718 cmELF elf(file.c_str());
2720 // Get the RPATH or RUNPATH entry from it.
2721 cmELF::StringEntry const* se = elf.GetRPath();
2722 if(!se)
2724 se = elf.GetRunPath();
2727 // Make sure the current rpath contains the new rpath.
2728 if(newRPath.empty())
2730 if(!se)
2732 return true;
2735 else
2737 if(se &&
2738 cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
2740 return true;
2743 return false;
2744 #else
2745 (void)file;
2746 (void)newRPath;
2747 return false;
2748 #endif