Browse Source

ENH: Allow blocking of writing into the source tree

Andy Cedilnik 19 năm trước cách đây
mục cha
commit
ee1975570e

+ 22 - 0
Source/cmAddCustomCommandCommand.cxx

@@ -204,6 +204,27 @@ bool cmAddCustomCommandCommand::InitialPass(
     return false;
     }
 
+  if ( !this->Makefile->CanIWriteThisFile(output.c_str()) )
+    {
+    std::string e = "attempted to have a file: " + output +
+      " in a source directory as an output of custom command.";
+    this->SetError(e.c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+    }
+  std::vector<std::string>::iterator oit;
+  for ( oit = outputs.begin(); oit != outputs.end(); ++ oit )
+    {
+    if ( !this->Makefile->CanIWriteThisFile(oit->c_str()) )
+      {
+      std::string e = "attempted to have a file: " + *oit +
+        " in a source directory as an output of custom command.";
+      this->SetError(e.c_str());
+      cmSystemTools::SetFatalErrorOccured();
+      return false;
+      }
+    }
+
   std::string::size_type pos = output.find_first_of("#<>");
   if(pos != output.npos)
     {
@@ -213,6 +234,7 @@ bool cmAddCustomCommandCommand::InitialPass(
     this->SetError(msg.str().c_str());
     return false;
     }
+
   // Choose which mode of the command to use.
   if(source.empty() && output.empty())
     {

+ 7 - 0
Source/cmConfigureFileCommand.cxx

@@ -28,6 +28,13 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args)
     }
   this->InputFile = args[0];
   this->OuputFile = args[1];
+  if ( !this->Makefile->CanIWriteThisFile(this->OuputFile.c_str()) )
+    {
+    std::string e = "attempted to configure a file: " + this->OuputFile + " into a source directory.";
+    this->SetError(e.c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+    }
   this->CopyOnly = false;
   this->EscapeQuotes = false;
 

+ 9 - 0
Source/cmExecuteProcessCommand.cxx

@@ -171,6 +171,15 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args)
       }
     }
 
+  if ( !this->Makefile->CanIWriteThisFile(output_file.c_str()) )
+    {
+    std::string e = "attempted to output into a file: " + output_file
+      + " into a source directory.";
+    this->SetError(e.c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+    }
+
   // Check for commands given.
   if(cmds.empty())
     {

+ 15 - 0
Source/cmFileCommand.cxx

@@ -102,6 +102,13 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args,
     {
     message += *i;
     }
+  if ( !this->Makefile->CanIWriteThisFile(fileName.c_str()) )
+    {
+    std::string e = "attempted to write a file: " + fileName + " into a source directory.";
+    this->SetError(e.c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+    }
   std::string dir = cmSystemTools::GetFilenamePath(fileName);
   cmSystemTools::MakeDirectory(dir.c_str());
 
@@ -279,6 +286,14 @@ bool cmFileCommand::HandleMakeDirectoryCommand(
       expr += "/" + *i;
       cdir = &expr;
       }
+    if ( !this->Makefile->CanIWriteThisFile(cdir->c_str()) )
+      {
+      std::string e = "attempted to create a directory: " + *cdir
+        + " into a source directory.";
+      this->SetError(e.c_str());
+      cmSystemTools::SetFatalErrorOccured();
+      return false;
+      }
     if ( !cmSystemTools::MakeDirectory(cdir->c_str()) )
       {
       std::string error = "problem creating directory: " + *cdir;

+ 8 - 0
Source/cmMakeDirectoryCommand.cxx

@@ -24,6 +24,14 @@ bool cmMakeDirectoryCommand::InitialPass(std::vector<std::string> const& args)
     this->SetError("called with incorrect number of arguments");
     return false;
     }
+    if ( !this->Makefile->CanIWriteThisFile(args[0].c_str()) )
+      {
+      std::string e = "attempted to create a directory: " + args[0]
+        + " into a source directory.";
+      this->SetError(e.c_str());
+      cmSystemTools::SetFatalErrorOccured();
+      return false;
+      }
   cmSystemTools::MakeDirectory(args[0].c_str());
   return true;
 }

+ 32 - 0
Source/cmMakefile.cxx

@@ -1320,6 +1320,33 @@ bool cmMakefile::IsSet(const char* name) const
   return true;
 }
 
+bool cmMakefile::CanIWriteThisFile(const char* fileName)
+{
+  if ( !this->IsOn("CMAKE_DISABLE_SOURCE_CHANGES") )
+    {
+    return 0;
+    }
+  // If we are doing an in-source build, than the test will always fail
+  if ( cmSystemTools::SameFile(this->GetHomeDirectory(), this->GetHomeOutputDirectory()) )
+    {
+    if ( this->IsOn("CMAKE_DISABLE_IN_SOURCE_BUILD") )
+      {
+      return false;
+      }
+    return true;
+    }
+
+  // Check if this is subdirectory of the source tree but not a subdirectory of a build tree
+  if ( cmSystemTools::IsSubDirectory(fileName,
+      this->GetHomeDirectory()) &&
+    !cmSystemTools::IsSubDirectory(fileName,
+      this->GetHomeOutputDirectory()) )
+    {
+    return false;
+    }
+  return true;
+}
+
 const char* cmMakefile::GetRequiredDefinition(const char* name) const
 {
   const char* ret = this->GetDefinition(name);
@@ -2328,6 +2355,11 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
                               bool copyonly, bool atOnly, bool escapeQuotes)
 {
   int res = 1;
+  if ( !this->CanIWriteThisFile(outfile) )
+    {
+    cmSystemTools::Error("Attempt to write file: ", outfile, " into a source directory.");
+    return 0;
+    }
   if ( !cmSystemTools::FileExists(infile) )
     {
     cmSystemTools::Error("File ", infile, " does not exist.");

+ 5 - 0
Source/cmMakefile.h

@@ -494,6 +494,11 @@ public:
    */
   const char* GetDefineFlags()
     {return this->DefineFlags.c_str();}
+
+  /**
+   * Make sure CMake can write this file
+   */
+  bool CanIWriteThisFile(const char* fileName);
   
   /**
    * Get the vector of used command instances.

+ 10 - 0
Source/cmWriteFileCommand.cxx

@@ -45,6 +45,16 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args)
       message += *i;
       }
     }
+
+  if ( !this->Makefile->CanIWriteThisFile(fileName.c_str()) )
+    {
+    std::string e = "attempted to write a file: " + fileName
+      + " into a source directory.";
+    this->SetError(e.c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+    }
+
   std::string dir = cmSystemTools::GetFilenamePath(fileName);
   cmSystemTools::MakeDirectory(dir.c_str());