Pārlūkot izejas kodu

configure_file: Add option to control file permissions transfer to copy

Issue: #20866
Rahul Gottipati 5 gadi atpakaļ
vecāks
revīzija
27b03281e2

+ 6 - 0
Help/command/configure_file.rst

@@ -7,6 +7,7 @@ Copy a file to another location and modify its contents.
 
   configure_file(<input> <output>
                  [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
+                 [NO_SOURCE_PERMISSIONS]
                  [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
 
 Copies an ``<input>`` file to an ``<output>`` file and substitutes
@@ -82,6 +83,11 @@ The arguments are:
   Restrict variable replacement to references of the form ``@VAR@``.
   This is useful for configuring scripts that use ``${VAR}`` syntax.
 
+ ``NO_SOURCE_PERMISSIONS``
+  Does not transfer the file permissions of the original file to the copy.
+  The copied file permissions default to the standard 644 value
+  (-rw-r--r--).
+
 ``NEWLINE_STYLE <style>``
   Specify the newline style for the output file.  Specify
   ``UNIX`` or ``LF`` for ``\n`` newlines, or specify

+ 5 - 0
Help/release/dev/configure_file-permission-control.rst

@@ -0,0 +1,5 @@
+configure_file-permission-control
+---------------------------------
+
+* The :command:`configure_file` command gained a ``NO_SOURCE_PERMISSIONS``
+  option to suppress copying the input file's permissions to the output file.

+ 1 - 1
Source/CPack/cmCPackGenerator.cxx

@@ -1326,7 +1326,7 @@ bool cmCPackGenerator::ConfigureFile(const std::string& inName,
                                      bool copyOnly /* = false */)
 {
   return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
-                                          false) == 1;
+                                          false, true) == 1;
 }
 
 int cmCPackGenerator::CleanTemporaryDirectory()

+ 5 - 1
Source/cmConfigureFileCommand.cxx

@@ -60,6 +60,7 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
   }
   bool copyOnly = false;
   bool escapeQuotes = false;
+  bool use_source_permissions = true;
 
   static std::set<cm::string_view> noopOptions = {
     /* Legacy.  */
@@ -87,6 +88,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
       escapeQuotes = true;
     } else if (args[i] == "@ONLY") {
       atOnly = true;
+    } else if (args[i] == "NO_SOURCE_PERMISSIONS") {
+      use_source_permissions = false;
     } else if (noopOptions.find(args[i]) != noopOptions.end()) {
       /* Ignore no-op options.  */
     } else {
@@ -102,7 +105,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
   }
 
   if (!status.GetMakefile().ConfigureFile(
-        inputFile, outputFile, copyOnly, atOnly, escapeQuotes, newLineStyle)) {
+        inputFile, outputFile, copyOnly, atOnly, escapeQuotes,
+        use_source_permissions, newLineStyle)) {
     status.SetError("Problem configuring file");
     return false;
   }

+ 1 - 1
Source/cmCreateTestSourceList.cxx

@@ -127,7 +127,7 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args,
   mf.AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", forwardDeclareCode);
   mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES", functionMapCode);
   bool res = true;
-  if (!mf.ConfigureFile(configFile, driver, false, true, false)) {
+  if (!mf.ConfigureFile(configFile, driver, false, true, false, true)) {
     res = false;
   }
 

+ 2 - 2
Source/cmLocalGenerator.cxx

@@ -3845,7 +3845,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
   cmLGInfoProp(mf, target, "MACOSX_BUNDLE_SHORT_VERSION_STRING");
   cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION");
   cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT");
-  mf->ConfigureFile(inFile, fname, false, false, false);
+  mf->ConfigureFile(inFile, fname, false, false, false, true);
 }
 
 void cmLocalGenerator::GenerateFrameworkInfoPList(
@@ -3881,7 +3881,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
   cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER");
   cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING");
   cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION");
-  mf->ConfigureFile(inFile, fname, false, false, false);
+  mf->ConfigureFile(inFile, fname, false, false, false, true);
 }
 
 namespace {

+ 16 - 1
Source/cmMakefile.cxx

@@ -34,6 +34,7 @@
 #include "cmExecutionStatus.h"
 #include "cmExpandedCommandArgument.h" // IWYU pragma: keep
 #include "cmExportBuildFileGenerator.h"
+#include "cmFSPermissions.h"
 #include "cmFileLockPool.h"
 #include "cmFunctionBlocker.h"
 #include "cmGeneratedFileStream.h"
@@ -69,6 +70,8 @@
 
 class cmMessenger;
 
+using namespace cmFSPermissions;
+
 cmDirectoryId::cmDirectoryId(std::string s)
   : String(std::move(s))
 {
@@ -3997,6 +4000,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
 int cmMakefile::ConfigureFile(const std::string& infile,
                               const std::string& outfile, bool copyonly,
                               bool atOnly, bool escapeQuotes,
+                              bool use_source_permissions,
                               cmNewLineStyle newLine)
 {
   int res = 1;
@@ -4020,7 +4024,13 @@ int cmMakefile::ConfigureFile(const std::string& infile,
   this->AddCMakeOutputFile(soutfile);
 
   mode_t perm = 0;
-  cmSystemTools::GetPermissions(sinfile, perm);
+  if (!use_source_permissions) {
+    perm = perm | mode_owner_read | mode_owner_write | mode_group_read |
+      mode_world_read;
+  } else {
+    cmSystemTools::GetPermissions(sinfile, perm);
+  }
+
   std::string::size_type pos = soutfile.rfind('/');
   if (pos != std::string::npos) {
     std::string path = soutfile.substr(0, pos);
@@ -4033,6 +4043,11 @@ int cmMakefile::ConfigureFile(const std::string& infile,
                          cmSystemTools::GetLastSystemError());
       return 0;
     }
+    if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+      this->IssueMessage(MessageType::FATAL_ERROR,
+                         cmSystemTools::GetLastSystemError());
+      return 0;
+    }
   } else {
     std::string newLineCharacters;
     std::ios::openmode omode = std::ios::out | std::ios::trunc;

+ 1 - 0
Source/cmMakefile.h

@@ -687,6 +687,7 @@ public:
    */
   int ConfigureFile(const std::string& infile, const std::string& outfile,
                     bool copyonly, bool atOnly, bool escapeQuotes,
+                    bool use_source_permissions,
                     cmNewLineStyle = cmNewLineStyle());
 
   /**

+ 1 - 1
Source/cmVisualStudio10TargetGenerator.cxx

@@ -670,7 +670,7 @@ void cmVisualStudio10TargetGenerator::Generate()
           cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
         ConvertToWindowsSlash(propsLocal);
         this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
-                                      true);
+                                      true, true);
         Elem(e1, "Import").Attribute("Project", propsLocal);
       }
     }

+ 10 - 0
Tests/RunCMake/configure_file/NoSourcePermissions.cmake

@@ -0,0 +1,10 @@
+configure_file(NoSourcePermissions.sh NoSourcePermissions.sh.out
+               NO_SOURCE_PERMISSIONS)
+
+if (UNIX)
+  execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/NoSourcePermissions.sh.out
+                  RESULT_VARIABLE result)
+  if (result EQUAL "0")
+    message(FATAL_ERROR "Copied file has executable permissions")
+  endif()
+endif()

+ 3 - 0
Tests/RunCMake/configure_file/NoSourcePermissions.sh

@@ -0,0 +1,3 @@
+#!/bin/sh
+
+#Testing NO_SOURCE_PERMISSIONS option of configure_file.

+ 1 - 0
Tests/RunCMake/configure_file/RunCMakeTest.cmake

@@ -15,6 +15,7 @@ run_cmake(NewLineStyle-NoArg)
 run_cmake(NewLineStyle-WrongArg)
 run_cmake(NewLineStyle-ValidArg)
 run_cmake(NewLineStyle-COPYONLY)
+run_cmake(NoSourcePermissions)
 
 if(RunCMake_GENERATOR MATCHES "Make")
   # Use a single build tree for a few tests without cleaning.