Bazel client: make jvm.log path platform-safe 

When writing the javalog.properties file that
configures the java logger, pass the log file path
in a platform safe manner. Namely if we're
running on Windows, don't write paths with
backslashes because they are mistaken for paths
with escaped characters.

Fixes: https://github.com/bazelbuild/bazel/issues/2576

--
Change-Id: Ibd907c13f1ffe4561c3a4e737f0c2b25ec5d4b17
Reviewed-on: https://cr.bazel.build/9059
PiperOrigin-RevId: 148342757
MOS_MIGRATED_REVID=148342757
diff --git a/src/main/cpp/blaze_util_platform.h b/src/main/cpp/blaze_util_platform.h
index 18efa8e..2f313a4 100644
--- a/src/main/cpp/blaze_util_platform.h
+++ b/src/main/cpp/blaze_util_platform.h
@@ -127,6 +127,10 @@
 // is Windows path list.
 std::string ConvertPathList(const std::string& path_list);
 
+// Converts `path` to a string that's safe to pass as path in a JVM flag.
+// See https://github.com/bazelbuild/bazel/issues/2576
+std::string PathAsJvmFlag(const std::string& path);
+
 // Return a string used to separate paths in a list.
 std::string ListSeparator();
 
diff --git a/src/main/cpp/blaze_util_posix.cc b/src/main/cpp/blaze_util_posix.cc
index d978607..3a4e713 100644
--- a/src/main/cpp/blaze_util_posix.cc
+++ b/src/main/cpp/blaze_util_posix.cc
@@ -163,6 +163,8 @@
 
 std::string ConvertPathList(const std::string& path_list) { return path_list; }
 
+std::string PathAsJvmFlag(const std::string& path) { return path; }
+
 std::string ListSeparator() { return ":"; }
 
 bool SymlinkDirectories(const string &target, const string &link) {
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index 73c5f35..8eb7a11 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -33,6 +33,7 @@
 #include <io.h>  // _open
 #endif  // COMPILER_MSVC
 
+#include <algorithm>
 #include <cstdio>
 #include <cstdlib>
 #include <sstream>
@@ -797,6 +798,15 @@
 
 string ListSeparator() { return ";"; }
 
+string PathAsJvmFlag(const string& path) {
+  // Convert backslashes to forward slashes, in order to avoid the JVM parsing
+  // Windows paths as if they contained escaped characters.
+  // See https://github.com/bazelbuild/bazel/issues/2576
+  string result(path);
+  std::replace(result.begin(), result.end(), '\\', '/');
+  return result;
+}
+
 string ConvertPath(const string& path) {
 #ifdef COMPILER_MSVC
   // This isn't needed when the binary isn't linked against msys-2.0.dll (when
diff --git a/src/main/cpp/startup_options.cc b/src/main/cpp/startup_options.cc
index a78b559..f7786b4 100644
--- a/src/main/cpp/startup_options.cc
+++ b/src/main/cpp/startup_options.cc
@@ -409,16 +409,18 @@
   // Configure logging
   const string propFile =
       blaze_util::JoinPath(output_base, "javalog.properties");
+  string java_log(
+      blaze::PathAsJvmFlag(blaze_util::JoinPath(output_base, "java.log")));
   if (!blaze_util::WriteFile("handlers=java.util.logging.FileHandler\n"
                              ".level=INFO\n"
                              "java.util.logging.FileHandler.level=INFO\n"
                              "java.util.logging.FileHandler.pattern=" +
-                                 blaze_util::JoinPath(output_base, "java.log") +
+                                 java_log +
                                  "\n"
                                  "java.util.logging.FileHandler.limit=50000\n"
                                  "java.util.logging.FileHandler.count=1\n"
-                                 "java.util.logging.FileHandler.formatter="
-                                 + java_logging_formatter + "\n",
+                                 "java.util.logging.FileHandler.formatter=" +
+                                 java_logging_formatter + "\n",
                              propFile)) {
     perror(("Couldn't write logging file " + propFile).c_str());
   } else {