summaryrefslogtreecommitdiffstats
path: root/Source/cmSystemTools.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmSystemTools.cxx')
-rw-r--r--Source/cmSystemTools.cxx146
1 files changed, 109 insertions, 37 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 9efc13b..8978e18 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -4,11 +4,12 @@
#include "cmAlgorithms.h"
#include "cmProcessOutput.h"
+#include "cm_sys_stat.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmArchiveWrite.h"
#include "cmLocale.h"
-#include <cm_libarchive.h>
+#include "cm_libarchive.h"
#ifndef __LA_INT64_T
#define __LA_INT64_T la_int64_t
#endif
@@ -26,15 +27,14 @@
#include "cmMachO.h"
#endif
+#include "cmsys/Directory.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/System.h"
+#include "cmsys/Terminal.h"
#include <algorithm>
#include <assert.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/Encoding.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/System.h>
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Terminal.h>
#include <ctype.h>
#include <errno.h>
#include <iostream>
@@ -43,8 +43,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
#include <time.h>
+#include <utility>
#if defined(_WIN32)
#include <windows.h>
@@ -505,6 +505,39 @@ void cmSystemTools::ParseUnixCommandLine(const char* command,
argv.Store(args);
}
+std::vector<std::string> cmSystemTools::HandleResponseFile(
+ std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd)
+{
+ std::vector<std::string> arg_full;
+ for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
+ std::string const& arg = *a;
+ if (cmHasLiteralPrefix(arg, "@")) {
+ cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in);
+ if (!responseFile) {
+ std::string error = "failed to open for reading (";
+ error += cmSystemTools::GetLastSystemError();
+ error += "):\n ";
+ error += arg.substr(1);
+ cmSystemTools::Error(error.c_str());
+ } else {
+ std::string line;
+ cmSystemTools::GetLineFromStream(responseFile, line);
+ std::vector<std::string> args2;
+#ifdef _WIN32
+ cmSystemTools::ParseWindowsCommandLine(line.c_str(), args2);
+#else
+ cmSystemTools::ParseUnixCommandLine(line.c_str(), args2);
+#endif
+ arg_full.insert(arg_full.end(), args2.begin(), args2.end());
+ }
+ } else {
+ arg_full.push_back(arg);
+ }
+ }
+ return arg_full;
+}
+
std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
{
std::vector<std::string> args;
@@ -570,6 +603,46 @@ std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
return args;
}
+size_t cmSystemTools::CalculateCommandLineLengthLimit()
+{
+ size_t sz =
+#ifdef _WIN32
+ // There's a maximum of 65536 bytes and thus 32768 WCHARs on Windows
+ // However, cmd.exe itself can only handle 8191 WCHARs and Ninja for
+ // example uses it to spawn processes.
+ size_t(8191);
+#elif defined(__linux)
+ // MAX_ARG_STRLEN is the maximum length of a string permissible for
+ // the execve() syscall on Linux. It's defined as (PAGE_SIZE * 32)
+ // in Linux's binfmts.h
+ static_cast<size_t>(sysconf(_SC_PAGESIZE) * 32);
+#else
+ size_t(0);
+#endif
+
+#if defined(_SC_ARG_MAX)
+ // ARG_MAX is the maximum size of the command and environment
+ // that can be passed to the exec functions on UNIX.
+ // The value in limits.h does not need to be present and may
+ // depend upon runtime memory constraints, hence sysconf()
+ // should be used to query it.
+ long szArgMax = sysconf(_SC_ARG_MAX);
+ // A return value of -1 signifies an undetermined limit, but
+ // it does not imply an infinite limit, and thus is ignored.
+ if (szArgMax != -1) {
+ // We estimate the size of the environment block to be 1000.
+ // This isn't accurate at all, but leaves some headroom.
+ szArgMax = szArgMax < 1000 ? 0 : szArgMax - 1000;
+#if defined(_WIN32) || defined(__linux)
+ sz = std::min(sz, static_cast<size_t>(szArgMax));
+#else
+ sz = static_cast<size_t>(szArgMax);
+#endif
+ }
+#endif
+ return sz;
+}
+
bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
std::string* captureStdOut,
std::string* captureStdErr, int* retVal,
@@ -617,8 +690,6 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) >
0) {
// Translate NULL characters in the output into valid text.
- // Visual Studio 7 puts these characters in the output of its
- // build process.
for (int i = 0; i < length; ++i) {
if (data[i] == '\0') {
data[i] = ' ';
@@ -1669,7 +1740,8 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
for (; outiter != out.end(); ++outiter) {
if ((*outiter == '\r') && ((outiter + 1) == out.end())) {
break;
- } else if (*outiter == '\n' || *outiter == '\0') {
+ }
+ if (*outiter == '\n' || *outiter == '\0') {
std::vector<char>::size_type length = outiter - out.begin();
if (length > 1 && *(outiter - 1) == '\r') {
--length;
@@ -1686,7 +1758,8 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
for (; erriter != err.end(); ++erriter) {
if ((*erriter == '\r') && ((erriter + 1) == err.end())) {
break;
- } else if (*erriter == '\n' || *erriter == '\0') {
+ }
+ if (*erriter == '\n' || *erriter == '\0') {
std::vector<char>::size_type length = erriter - err.begin();
if (length > 1 && *(erriter - 1) == '\r') {
--length;
@@ -1978,6 +2051,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
// ???
}
#endif
+ exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir);
cmSystemToolsCMakeCommand = exe_dir;
cmSystemToolsCMakeCommand += "/cmake";
cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension();
@@ -2015,8 +2089,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
// Install tree has
// - "<prefix><CMAKE_BIN_DIR>/cmake"
// - "<prefix><CMAKE_DATA_DIR>"
- const std::string actual_case = cmSystemTools::GetActualCaseForPath(exe_dir);
- if (cmHasSuffix(actual_case, CMAKE_BIN_DIR)) {
+ if (cmHasSuffix(exe_dir, CMAKE_BIN_DIR)) {
std::string const prefix =
exe_dir.substr(0, exe_dir.size() - strlen(CMAKE_BIN_DIR));
cmSystemToolsCMakeRoot = prefix + CMAKE_DATA_DIR;
@@ -2585,29 +2658,28 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
it = dentries.erase(it);
entriesErased++;
continue;
- } else {
- if (cmELF::TagMipsRldMapRel != 0 &&
- it->first == cmELF::TagMipsRldMapRel) {
- // Background: debuggers need to know the "linker map" which contains
- // the addresses each dynamic object is loaded at. Most arches use
- // the DT_DEBUG tag which the dynamic linker writes to (directly) and
- // contain the location of the linker map, however on MIPS the
- // .dynamic section is always read-only so this is not possible. MIPS
- // objects instead contain a DT_MIPS_RLD_MAP tag which contains the
- // address where the dyanmic linker will write to (an indirect
- // version of DT_DEBUG). Since this doesn't work when using PIE, a
- // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this
- // version contains a relative offset, moving it changes the
- // calculated address. This may cause the dyanmic linker to write
- // into memory it should not be changing.
- //
- // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
- // we move it up by n bytes, we add n bytes to the value of this tag.
- it->second += entriesErased * sizeof_dentry;
- }
-
- it++;
}
+ if (cmELF::TagMipsRldMapRel != 0 &&
+ it->first == cmELF::TagMipsRldMapRel) {
+ // Background: debuggers need to know the "linker map" which contains
+ // the addresses each dynamic object is loaded at. Most arches use
+ // the DT_DEBUG tag which the dynamic linker writes to (directly) and
+ // contain the location of the linker map, however on MIPS the
+ // .dynamic section is always read-only so this is not possible. MIPS
+ // objects instead contain a DT_MIPS_RLD_MAP tag which contains the
+ // address where the dyanmic linker will write to (an indirect
+ // version of DT_DEBUG). Since this doesn't work when using PIE, a
+ // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this
+ // version contains a relative offset, moving it changes the
+ // calculated address. This may cause the dyanmic linker to write
+ // into memory it should not be changing.
+ //
+ // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
+ // we move it up by n bytes, we add n bytes to the value of this tag.
+ it->second += entriesErased * sizeof_dentry;
+ }
+
+ it++;
}
// Encode new entries list