Thread premissions through sys::fs::create_director{y|ies}

llvm-svn: 244268
diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h
index a736c32..36c669a 100644
--- a/llvm/include/llvm/Support/FileSystem.h
+++ b/llvm/include/llvm/Support/FileSystem.h
@@ -285,7 +285,8 @@
 ///          specific error_code. If IgnoreExisting is false, also returns
 ///          error if the directory already existed.
 std::error_code create_directories(const Twine &path,
-                                   bool IgnoreExisting = true);
+                                   bool IgnoreExisting = true,
+                                   perms Perms = owner_all | group_all);
 
 /// @brief Create the directory in path.
 ///
@@ -293,7 +294,8 @@
 /// @returns errc::success if is_directory(path), otherwise a platform
 ///          specific error_code. If IgnoreExisting is false, also returns
 ///          error if the directory already existed.
-std::error_code create_directory(const Twine &path, bool IgnoreExisting = true);
+std::error_code create_directory(const Twine &path, bool IgnoreExisting = true,
+                                 perms Perms = owner_all | group_all);
 
 /// @brief Create a link from \a from to \a to.
 ///
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 985cdbf..54daf24 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -785,12 +785,13 @@
                    "occurred above!");
 }
 
-std::error_code create_directories(const Twine &Path, bool IgnoreExisting) {
+std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
+                                   perms Perms) {
   SmallString<128> PathStorage;
   StringRef P = Path.toStringRef(PathStorage);
 
   // Be optimistic and try to create the directory
-  std::error_code EC = create_directory(P, IgnoreExisting);
+  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
   // If we succeeded, or had any error other than the parent not existing, just
   // return it.
   if (EC != errc::no_such_file_or_directory)
@@ -802,10 +803,10 @@
   if (Parent.empty())
     return EC;
 
-  if ((EC = create_directories(Parent)))
+  if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
       return EC;
 
-  return create_directory(P, IgnoreExisting);
+  return create_directory(P, IgnoreExisting, Perms);
 }
 
 std::error_code copy_file(const Twine &From, const Twine &To) {
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index 973d010..a77efcc 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -219,11 +219,12 @@
   return std::error_code();
 }
 
-std::error_code create_directory(const Twine &path, bool IgnoreExisting) {
+std::error_code create_directory(const Twine &path, bool IgnoreExisting,
+                                 perms Perms) {
   SmallString<128> path_storage;
   StringRef p = path.toNullTerminatedStringRef(path_storage);
 
-  if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) {
+  if (::mkdir(p.begin(), Perms) == -1) {
     if (errno != EEXIST || !IgnoreExisting)
       return std::error_code(errno, std::generic_category());
   }
diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index 72da7c5..3033149 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -182,7 +182,8 @@
   return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result);
 }
 
-std::error_code create_directory(const Twine &path, bool IgnoreExisting) {
+std::error_code create_directory(const Twine &path, bool IgnoreExisting,
+                                 perms Perms) {
   SmallVector<wchar_t, 128> path_utf16;
 
   if (std::error_code ec = widenPath(path, path_utf16))
diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp
index 210b3a0..11d53c8 100644
--- a/llvm/unittests/Support/Path.cpp
+++ b/llvm/unittests/Support/Path.cpp
@@ -20,6 +20,10 @@
 #include <winerror.h>
 #endif
 
+#ifdef LLVM_ON_UNIX
+#include <sys/stat.h>
+#endif
+
 using namespace llvm;
 using namespace llvm::sys;
 
@@ -458,6 +462,26 @@
             errc::file_exists);
   ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo"));
 
+#ifdef LLVM_ON_UNIX
+  // Set a 0000 umask so that we can test our directory permissions.
+  mode_t OldUmask = ::umask(0000);
+
+  fs::file_status Status;
+  ASSERT_NO_ERROR(
+      fs::create_directory(Twine(TestDirectory) + "baz500", false,
+                           fs::perms::owner_read | fs::perms::owner_exe));
+  ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz500", Status));
+  ASSERT_EQ(Status.permissions() & fs::perms::all_all,
+            fs::perms::owner_read | fs::perms::owner_exe);
+  ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "baz777", false,
+                                       fs::perms::all_all));
+  ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz777", Status));
+  ASSERT_EQ(Status.permissions() & fs::perms::all_all, fs::perms::all_all);
+
+  // Restore umask to be safe.
+  ::umask(OldUmask);
+#endif
+
 #ifdef LLVM_ON_WIN32
   // Prove that create_directories() can handle a pathname > 248 characters,
   // which is the documented limit for CreateDirectory().