Don't clobber install_base's parent's permissions

Previously we'd unconditionally try to set dirname(install_base)'s mode to
0777, then again set it to umask.

TESTED: Confirmed --install_base=/tmp/foo worked, and $unwritabledir/baz failed
PiperOrigin-RevId: 303407664
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc
index 4a636e8..e21e354 100644
--- a/src/main/cpp/util/file_posix.cc
+++ b/src/main/cpp/util/file_posix.cc
@@ -128,8 +128,8 @@
 string CreateTempDir(const std::string &prefix) {
   std::string parent = Dirname(prefix);
   // Need parent to exist first.
-  // TODO(b/150220877): Avoid trying to recreate a dir that already exists.
-  if (!blaze_util::MakeDirectories(parent, 0777)) {
+  if (!blaze_util::PathExists(parent) &&
+      !blaze_util::MakeDirectories(parent, 0777)) {
     BAZEL_DIE(blaze_exit_code::INTERNAL_ERROR)
         << "couldn't create '" << parent << "': "
         << blaze_util::GetLastErrorString();
@@ -139,8 +139,8 @@
   if (mkdtemp(&result[0]) == nullptr) {
     std::string err = GetLastErrorString();
     BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
-        << "could not create temporary directory to extract install base"
-        << " (" << err << ")";
+        << "could not create temporary directory under " << parent
+        << " to extract install base into (" << err << ")";
   }
 
   // There's no better way to get the current umask than to set and reset it.
diff --git a/src/test/cpp/util/file_posix_test.cc b/src/test/cpp/util/file_posix_test.cc
index 1668791..f485842 100644
--- a/src/test/cpp/util/file_posix_test.cc
+++ b/src/test/cpp/util/file_posix_test.cc
@@ -364,4 +364,21 @@
   EXPECT_TRUE(PathExists(file_symlink_target));
 }
 
+TEST(FileTest, TestCreateTempDirDoesntClobberParentPerms) {
+  const char* tempdir_cstr = getenv("TEST_TMPDIR");
+  ASSERT_NE(tempdir_cstr, nullptr);
+  string tempdir(tempdir_cstr);
+  ASSERT_TRUE(PathExists(tempdir));
+
+  string existing_parent_dir(JoinPath(tempdir, "existing"));
+  ASSERT_TRUE(MakeDirectories(existing_parent_dir, 0700));
+  string prefix(JoinPath(existing_parent_dir, "mytmp"));
+  string result(CreateTempDir(prefix));
+  ASSERT_EQ(0, result.find(prefix));
+  EXPECT_TRUE(PathExists(result));
+  struct stat filestat = {};
+  ASSERT_EQ(0, stat(existing_parent_dir.c_str(), &filestat));
+  ASSERT_EQ(mode_t(0700), filestat.st_mode & 0777);
+}
+
 }  // namespace blaze_util