[flang] Make module files read-only.
authorTim Keith <tkeith@nvidia.com>
Thu, 2 Aug 2018 23:38:36 +0000 (16:38 -0700)
committerTim Keith <tkeith@nvidia.com>
Thu, 2 Aug 2018 23:38:36 +0000 (16:38 -0700)
Original-commit: flang-compiler/f18@c7752ab5fb8736991634ee068fdda59f1af28e71
Reviewed-on: https://github.com/flang-compiler/f18/pull/160
Tree-same-pre-rewrite: false

flang/lib/semantics/mod-file.cc

index d3766d2..72ca96a 100644 (file)
@@ -24,6 +24,9 @@
 #include <ostream>
 #include <set>
 #include <sstream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 #include <vector>
 
 namespace Fortran::semantics {
@@ -54,6 +57,7 @@ static std::ostream &PutLower(std::ostream &, const Symbol &);
 static std::ostream &PutLower(std::ostream &, const DeclTypeSpec &);
 static std::ostream &PutLower(std::ostream &, const std::string &);
 static std::string CheckSum(const std::string &);
+static bool MakeReadonly(const std::string &);
 
 bool ModFileWriter::WriteAll() {
   WriteChildren(Scope::globalScope);
@@ -75,6 +79,7 @@ void ModFileWriter::WriteOne(const Scope &scope) {
     auto *ancestor{symbol->get<ModuleDetails>().ancestor()};
     auto ancestorName{ancestor ? ancestor->name().ToString() : ""s};
     auto path{ModFilePath(dir_, symbol->name(), ancestorName)};
+    unlink(path.data());
     std::ofstream os{path};
     PutSymbols(scope);
     std::string all{GetAsString(*symbol)};
@@ -86,6 +91,10 @@ void ModFileWriter::WriteOne(const Scope &scope) {
           "Error writing %s: %s"_err_en_US, path.c_str(), std::strerror(errno));
       return;
     }
+    if (!MakeReadonly(path)) {
+      errors_.emplace_back("Error changing permissions on %s: %s"_en_US,
+          path.c_str(), std::strerror(errno));
+    }
   }
   WriteChildren(scope);  // write out submodules
 }
@@ -478,6 +487,16 @@ static std::string ModFilePath(const std::string &dir, const SourceName &name,
   return path.str();
 }
 
+static bool MakeReadonly(const std::string &path) {
+  struct stat statbuf;
+  if (stat(path.c_str(), &statbuf) != 0) {
+    return false;
+  }
+  auto mode{statbuf.st_mode};
+  mode &= S_IRUSR | S_IRGRP | S_IROTH;
+  return chmod(path.data(), mode) == 0;
+}
+
 static parser::Message Error(const SourceName &location,
     parser::MessageFixedText fixedText, const std::string &arg) {
   return parser::Message{