aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2017-01-10 10:41:26 +0000
committerGravatar Marcel Hlopko <hlopko@google.com>2017-01-10 11:51:20 +0000
commit44ecf9a0c7c25496a43f59f1c8f20df9527e12cb (patch)
treec7580369cd3b0e7426b569d9638addaec4c00b0d
parent12bf5ba34f70200eccc9e5f9b2f27d91d4514d77 (diff)
Windows: implement and use AsShortWindowsPath
Because CreateProcessW doesn't support long paths, not even with the "\\?\" prefix [1], we need to convert long paths to short ones to spawn processes. This change implements the corresponding function and uses it in blaze_util_windows. [1] https://github.com/bazelbuild/bazel/issues/2181#issuecomment-270696173 See https://github.com/bazelbuild/bazel/issues/2107 See https://github.com/bazelbuild/bazel/issues/2181 -- PiperOrigin-RevId: 144062404 MOS_MIGRATED_REVID=144062404
-rw-r--r--src/main/cpp/blaze_util_windows.cc24
-rw-r--r--src/main/cpp/util/file_platform.h4
-rw-r--r--src/main/cpp/util/file_windows.cc27
-rw-r--r--src/test/cpp/util/file_windows_test.cc19
4 files changed, 65 insertions, 9 deletions
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index 12aa3e3721..0595de6bcf 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -373,6 +373,12 @@ struct CmdLine {
static void CreateCommandLine(CmdLine* result, const string& exe,
const vector<string>& args_vector) {
std::ostringstream cmdline;
+ string short_exe;
+ if (!blaze_util::AsShortWindowsPath(exe + ".exe", &short_exe)) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "CreateCommandLine: AsShortWindowsPath(%s.exe) failed, err=%d",
+ exe.c_str(), GetLastError());
+ }
bool first = true;
for (const auto& s : args_vector) {
if (first) {
@@ -456,23 +462,23 @@ string GetJvmVersion(const string& java_exe) {
}
PROCESS_INFORMATION processInfo = {0};
- STARTUPINFOW startupInfo = {0};
+ STARTUPINFOA startupInfo = {0};
startupInfo.hStdError = pipe_write;
startupInfo.hStdOutput = pipe_write;
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
- wstring wjava_exe;
- if (!blaze_util::AsWindowsPath(java_exe, &wjava_exe)) {
+ string win_java_exe;
+ if (!blaze_util::AsShortWindowsPath(java_exe + ".exe", &win_java_exe)) {
CloseHandle(pipe_read);
CloseHandle(pipe_write);
- pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "AsWindowsPath(%s)",
- java_exe);
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "GetJvmVersion: AsWindowsPath(%s.exe)", java_exe.c_str());
}
- wjava_exe = wstring(L"\"") + wjava_exe + L".exe\" -version";
+ win_java_exe = string("\"") + win_java_exe + "\" -version";
- WCHAR cmdline[MAX_CMDLINE_LENGTH];
- wcscpy(cmdline, wjava_exe.c_str());
- BOOL ok = CreateProcessW(
+ char cmdline[MAX_CMDLINE_LENGTH];
+ strncpy(cmdline, win_java_exe.c_str(), win_java_exe.size() + 1);
+ BOOL ok = CreateProcessA(
/* lpApplicationName */ NULL,
/* lpCommandLine */ cmdline,
/* lpProcessAttributes */ NULL,
diff --git a/src/main/cpp/util/file_platform.h b/src/main/cpp/util/file_platform.h
index 9c95468e4b..91fc086627 100644
--- a/src/main/cpp/util/file_platform.h
+++ b/src/main/cpp/util/file_platform.h
@@ -133,6 +133,10 @@ void ForEachDirectoryEntry(const std::string &path,
// prepend the UNC prefix in case they need to pass it to a WinAPI function
// (some require the prefix, some don't), or to quote the path if necessary.
bool AsWindowsPath(const std::string &path, std::wstring *result);
+
+// Same as `AsWindowsPath`, but returns a lowercase 8dot3 style shortened path.
+// Result will never have a UNC prefix.
+bool AsShortWindowsPath(const std::string &path, std::string *result);
#endif // defined(COMPILER_MSVC) || defined(__CYGWIN__)
} // namespace blaze_util
diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc
index 75555bba89..3fa01a445b 100644
--- a/src/main/cpp/util/file_windows.cc
+++ b/src/main/cpp/util/file_windows.cc
@@ -308,6 +308,8 @@ bool AsWindowsPath(const string& path, wstring* result) {
static bool AsWindowsPathWithUncPrefix(const string& path, wstring* wpath) {
if (!AsWindowsPath(path, wpath)) {
+ PrintError("AsWindowsPathWithUncPrefix(%s): AsWindowsPath failed, err=%d\n",
+ path.c_str(), GetLastError());
return false;
}
if (!IsAbsolute(path)) {
@@ -317,6 +319,31 @@ static bool AsWindowsPathWithUncPrefix(const string& path, wstring* wpath) {
return true;
}
+bool AsShortWindowsPath(const string& path, string* result) {
+ result->clear();
+ wstring wpath;
+ if (!AsWindowsPathWithUncPrefix(path, &wpath)) {
+ return false;
+ }
+ DWORD size = ::GetShortPathNameW(wpath.c_str(), nullptr, 0);
+ if (size == 0) {
+ return false;
+ }
+
+ unique_ptr<WCHAR[]> wshort(new WCHAR[size]); // size includes null-terminator
+ if (size - 1 != ::GetShortPathNameW(wpath.c_str(), wshort.get(), size)) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "AsShortWindowsPath(%s): GetShortPathNameW(%S) failed, err=%d",
+ path.c_str(), wpath.c_str(), GetLastError());
+ }
+ // GetShortPathNameW may preserve the UNC prefix in the result, so strip it.
+ WCHAR* result_ptr = wshort.get() + (HasUncPrefix(wshort.get()) ? 4 : 0);
+
+ result->assign(WstringToCstring(result_ptr).get());
+ ToLower(result);
+ return true;
+}
+
bool ReadFile(const string& filename, string* content, int max_size) {
if (filename.empty()) {
return false;
diff --git a/src/test/cpp/util/file_windows_test.cc b/src/test/cpp/util/file_windows_test.cc
index 983763aeaf..1cf49d88c5 100644
--- a/src/test/cpp/util/file_windows_test.cc
+++ b/src/test/cpp/util/file_windows_test.cc
@@ -178,6 +178,25 @@ TEST(FileTest, TestAsWindowsPath) {
ASSERT_EQ(wlongpath, actual);
}
+TEST(FileTest, TestAsShortWindowsPath) {
+ string tmpdir(GetTestTmpDir());
+ ASSERT_LT(0, tmpdir.size());
+
+ string short_tmpdir;
+ ASSERT_TRUE(AsShortWindowsPath(tmpdir, &short_tmpdir));
+ ASSERT_LT(0, short_tmpdir.size());
+ ASSERT_TRUE(PathExists(short_tmpdir));
+
+ string dirname(JoinPath(short_tmpdir, "LONGpathNAME"));
+ ASSERT_EQ(0, mkdir(dirname.c_str()));
+ ASSERT_TRUE(PathExists(dirname));
+
+ string actual;
+ ASSERT_TRUE(AsShortWindowsPath(dirname, &actual));
+ ASSERT_EQ(short_tmpdir + "\\longpa~1", actual);
+ ASSERT_EQ(0, rmdir(dirname.c_str()));
+}
+
TEST(FileTest, TestMsysRootRetrieval) {
wstring actual;