فهرست منبع

configure_file: Add option for user defined permissions

User defined permissions and options to copy permissions are
implemented.

Fixes: #20866
Asit Dhal 5 سال پیش
والد
کامیت
03ad0e61c1
30فایلهای تغییر یافته به همراه266 افزوده شده و 28 حذف شده
  1. 8 1
      Help/command/configure_file.rst
  2. 6 0
      Help/release/dev/configure_file-user-permissions.rst
  3. 1 1
      Source/CPack/cmCPackGenerator.cxx
  4. 104 5
      Source/cmConfigureFileCommand.cxx
  5. 1 1
      Source/cmCreateTestSourceList.cxx
  6. 2 2
      Source/cmLocalGenerator.cxx
  7. 5 15
      Source/cmMakefile.cxx
  8. 3 2
      Source/cmMakefile.h
  9. 1 1
      Source/cmVisualStudio10TargetGenerator.cxx
  10. 7 0
      Tests/RunCMake/configure_file/RunCMakeTest.cmake
  11. 0 0
      Tests/RunCMake/configure_file/SourcePermissions-result.txt
  12. 0 0
      Tests/RunCMake/configure_file/SourcePermissions-stderr.txt
  13. 34 0
      Tests/RunCMake/configure_file/SourcePermissions.cmake
  14. 1 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-result.txt
  15. 5 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-stderr.txt
  16. 5 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1.cmake
  17. 1 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-result.txt
  18. 5 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-stderr.txt
  19. 5 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2.cmake
  20. 1 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-result.txt
  21. 5 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-stderr.txt
  22. 5 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3.cmake
  23. 1 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-result.txt
  24. 4 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-stderr.txt
  25. 4 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4.cmake
  26. 1 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-result.txt
  27. 4 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-stderr.txt
  28. 6 0
      Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5.cmake
  29. 40 0
      Tests/RunCMake/configure_file/UseSourcePermissions.cmake
  30. 1 0
      Tests/RunCMake/configure_file/sourcefile.txt

+ 8 - 1
Help/command/configure_file.rst

@@ -6,8 +6,9 @@ Copy a file to another location and modify its contents.
 .. code-block:: cmake
 
   configure_file(<input> <output>
+                 [FILE_PERMISSIONS <permissions>...]
                  [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
-                 [NO_SOURCE_PERMISSIONS]
+                 [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
                  [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
 
 Copies an ``<input>`` file to an ``<output>`` file and substitutes
@@ -72,6 +73,9 @@ The arguments are:
   If the path names an existing directory the output file is placed
   in that directory with the same file name as the input file.
 
+``FILE_PERMISSIONS <permissions>...``
+  Use user provided permissions for the output file.
+
 ``COPYONLY``
   Copy the file without replacing any variable references or other
   content.  This option may not be used with ``NEWLINE_STYLE``.
@@ -88,6 +92,9 @@ The arguments are:
   The copied file permissions default to the standard 644 value
   (-rw-r--r--).
 
+``USE_SOURCE_PERMISSIONS``
+  Transfer the file permissions of the original file to the output file.
+
 ``NEWLINE_STYLE <style>``
   Specify the newline style for the output file.  Specify
   ``UNIX`` or ``LF`` for ``\n`` newlines, or specify

+ 6 - 0
Help/release/dev/configure_file-user-permissions.rst

@@ -0,0 +1,6 @@
+configure_file-user-permissions
+-------------------------------
+
+* The :command:`configure_file` command gained a ``USE_SOURCE_PERMISSIONS``
+  and ``FILE_PERMISSIONS`` option to support copying of permissions of source
+  file and specifying user defined permissions.

+ 1 - 1
Source/CPack/cmCPackGenerator.cxx

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

+ 104 - 5
Source/cmConfigureFileCommand.cxx

@@ -3,11 +3,15 @@
 #include "cmConfigureFileCommand.h"
 
 #include <set>
+#include <sstream>
 
 #include <cm/string_view>
 #include <cmext/string_view>
 
+#include <sys/types.h>
+
 #include "cmExecutionStatus.h"
+#include "cmFSPermissions.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmNewLineStyle.h"
@@ -60,7 +64,19 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
   }
   bool copyOnly = false;
   bool escapeQuotes = false;
-  bool use_source_permissions = true;
+  bool useSourcePermissions = false;
+  bool noSourcePermissions = false;
+  bool filePermissions = false;
+  std::vector<std::string> filePermissionOptions;
+
+  enum class Doing
+  {
+    DoingNone,
+    DoingFilePermissions,
+    DoneFilePermissions
+  };
+
+  Doing doing = Doing::DoingNone;
 
   static std::set<cm::string_view> noopOptions = {
     /* Legacy.  */
@@ -78,6 +94,9 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
   bool atOnly = false;
   for (unsigned int i = 2; i < args.size(); ++i) {
     if (args[i] == "COPYONLY") {
+      if (doing == Doing::DoingFilePermissions) {
+        doing = Doing::DoneFilePermissions;
+      }
       copyOnly = true;
       if (newLineStyle.IsValid()) {
         status.SetError("COPYONLY could not be used in combination "
@@ -85,13 +104,49 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
         return false;
       }
     } else if (args[i] == "ESCAPE_QUOTES") {
+      if (doing == Doing::DoingFilePermissions) {
+        doing = Doing::DoneFilePermissions;
+      }
       escapeQuotes = true;
     } else if (args[i] == "@ONLY") {
+      if (doing == Doing::DoingFilePermissions) {
+        doing = Doing::DoneFilePermissions;
+      }
       atOnly = true;
     } else if (args[i] == "NO_SOURCE_PERMISSIONS") {
-      use_source_permissions = false;
+      if (doing == Doing::DoingFilePermissions) {
+        status.SetError(" given both FILE_PERMISSIONS and "
+                        "NO_SOURCE_PERMISSIONS. Only one option allowed.");
+        return false;
+      }
+      noSourcePermissions = true;
+    } else if (args[i] == "USE_SOURCE_PERMISSIONS") {
+      if (doing == Doing::DoingFilePermissions) {
+        status.SetError(" given both FILE_PERMISSIONS and "
+                        "USE_SOURCE_PERMISSIONS. Only one option allowed.");
+        return false;
+      }
+      useSourcePermissions = true;
+    } else if (args[i] == "FILE_PERMISSIONS") {
+      if (useSourcePermissions) {
+        status.SetError(" given both FILE_PERMISSIONS and "
+                        "USE_SOURCE_PERMISSIONS. Only one option allowed.");
+        return false;
+      }
+      if (noSourcePermissions) {
+        status.SetError(" given both FILE_PERMISSIONS and "
+                        "NO_SOURCE_PERMISSIONS. Only one option allowed.");
+        return false;
+      }
+
+      if (doing == Doing::DoingNone) {
+        doing = Doing::DoingFilePermissions;
+        filePermissions = true;
+      }
     } else if (noopOptions.find(args[i]) != noopOptions.end()) {
       /* Ignore no-op options.  */
+    } else if (doing == Doing::DoingFilePermissions) {
+      filePermissionOptions.push_back(args[i]);
     } else {
       unknown_args += " ";
       unknown_args += args[i];
@@ -104,9 +159,53 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
     status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, msg);
   }
 
-  if (!status.GetMakefile().ConfigureFile(
-        inputFile, outputFile, copyOnly, atOnly, escapeQuotes,
-        use_source_permissions, newLineStyle)) {
+  if (useSourcePermissions && noSourcePermissions) {
+    status.SetError(" given both USE_SOURCE_PERMISSIONS and "
+                    "NO_SOURCE_PERMISSIONS. Only one option allowed.");
+    return false;
+  }
+
+  mode_t permisiions = 0;
+
+  if (filePermissions) {
+    if (filePermissionOptions.empty()) {
+      status.SetError(" given FILE_PERMISSIONS without any options.");
+      return false;
+    }
+
+    std::vector<std::string> invalidOptions;
+    for (auto const& e : filePermissionOptions) {
+      if (!cmFSPermissions::stringToModeT(e, permisiions)) {
+        invalidOptions.push_back(e);
+      }
+    }
+
+    if (!invalidOptions.empty()) {
+      std::ostringstream oss;
+      oss << " given invalid permission ";
+      for (auto i = 0u; i < invalidOptions.size(); i++) {
+        if (i == 0u) {
+          oss << "\"" << invalidOptions[i] << "\"";
+        } else {
+          oss << ",\"" << invalidOptions[i] << "\"";
+        }
+      }
+      oss << ".";
+      status.SetError(oss.str());
+      return false;
+    }
+  }
+
+  if (noSourcePermissions) {
+    permisiions |= cmFSPermissions::mode_owner_read;
+    permisiions |= cmFSPermissions::mode_owner_write;
+    permisiions |= cmFSPermissions::mode_group_read;
+    permisiions |= cmFSPermissions::mode_world_read;
+  }
+
+  if (!status.GetMakefile().ConfigureFile(inputFile, outputFile, copyOnly,
+                                          atOnly, escapeQuotes, permisiions,
+                                          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, true)) {
+  if (!mf.ConfigureFile(configFile, driver, false, true, false)) {
     res = false;
   }
 

+ 2 - 2
Source/cmLocalGenerator.cxx

@@ -3768,7 +3768,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, true);
+  mf->ConfigureFile(inFile, fname, false, false, false);
 }
 
 void cmLocalGenerator::GenerateFrameworkInfoPList(
@@ -3803,7 +3803,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, true);
+  mf->ConfigureFile(inFile, fname, false, false, false);
 }
 
 namespace {

+ 5 - 15
Source/cmMakefile.cxx

@@ -29,15 +29,12 @@
 #include "cmsys/FStream.hxx"
 #include "cmsys/RegularExpression.hxx"
 
-#include "cm_sys_stat.h"
-
 #include "cmCommandArgumentParserHelper.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
 #include "cmExecutionStatus.h"
 #include "cmExpandedCommandArgument.h" // IWYU pragma: keep
 #include "cmExportBuildFileGenerator.h"
-#include "cmFSPermissions.h"
 #include "cmFileLockPool.h"
 #include "cmFunctionBlocker.h"
 #include "cmGeneratedFileStream.h"
@@ -72,8 +69,6 @@
 
 class cmMessenger;
 
-using namespace cmFSPermissions;
-
 cmDirectoryId::cmDirectoryId(std::string s)
   : String(std::move(s))
 {
@@ -3850,8 +3845,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)
+                              mode_t permissions, cmNewLineStyle newLine)
 {
   int res = 1;
   if (!this->CanIWriteThisFile(outfile)) {
@@ -3873,12 +3867,8 @@ int cmMakefile::ConfigureFile(const std::string& infile,
   // output files that now don't exist.
   this->AddCMakeOutputFile(soutfile);
 
-  mode_t perm = 0;
-  if (!use_source_permissions) {
-    perm = perm | mode_owner_read | mode_owner_write | mode_group_read |
-      mode_world_read;
-  } else {
-    cmSystemTools::GetPermissions(sinfile, perm);
+  if (permissions == 0) {
+    cmSystemTools::GetPermissions(sinfile, permissions);
   }
 
   std::string::size_type pos = soutfile.rfind('/');
@@ -3893,7 +3883,7 @@ int cmMakefile::ConfigureFile(const std::string& infile,
                          cmSystemTools::GetLastSystemError());
       return 0;
     }
-    if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+    if (!cmSystemTools::SetPermissions(soutfile, permissions)) {
       this->IssueMessage(MessageType::FATAL_ERROR,
                          cmSystemTools::GetLastSystemError());
       return 0;
@@ -3950,7 +3940,7 @@ int cmMakefile::ConfigureFile(const std::string& infile,
                          cmSystemTools::GetLastSystemError());
       res = 0;
     } else {
-      if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+      if (!cmSystemTools::SetPermissions(soutfile, permissions)) {
         this->IssueMessage(MessageType::FATAL_ERROR,
                            cmSystemTools::GetLastSystemError());
         res = 0;

+ 3 - 2
Source/cmMakefile.h

@@ -20,6 +20,8 @@
 
 #include "cmsys/RegularExpression.hxx"
 
+#include "cm_sys_stat.h"
+
 #include "cmAlgorithms.h"
 #include "cmCustomCommandTypes.h"
 #include "cmListFileCache.h"
@@ -659,8 +661,7 @@ public:
    */
   int ConfigureFile(const std::string& infile, const std::string& outfile,
                     bool copyonly, bool atOnly, bool escapeQuotes,
-                    bool use_source_permissions,
-                    cmNewLineStyle = cmNewLineStyle());
+                    mode_t permissions = 0, cmNewLineStyle = cmNewLineStyle());
 
   /**
    * Print a command's invocation

+ 1 - 1
Source/cmVisualStudio10TargetGenerator.cxx

@@ -676,7 +676,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);
       }
     }

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

@@ -16,6 +16,13 @@ run_cmake(NewLineStyle-WrongArg)
 run_cmake(NewLineStyle-ValidArg)
 run_cmake(NewLineStyle-COPYONLY)
 run_cmake(NoSourcePermissions)
+run_cmake(SourcePermissionsInvalidArg-1)
+run_cmake(SourcePermissionsInvalidArg-2)
+run_cmake(SourcePermissionsInvalidArg-3)
+run_cmake(SourcePermissionsInvalidArg-4)
+run_cmake(SourcePermissionsInvalidArg-5)
+run_cmake(UseSourcePermissions)
+run_cmake(SourcePermissions)
 
 if(RunCMake_GENERATOR MATCHES "Make")
   # Use a single build tree for a few tests without cleaning.

+ 0 - 0
Tests/RunCMake/configure_file/SourcePermissions-result.txt


+ 0 - 0
Tests/RunCMake/configure_file/SourcePermissions-stderr.txt


+ 34 - 0
Tests/RunCMake/configure_file/SourcePermissions.cmake

@@ -0,0 +1,34 @@
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt
+    FILE_PERMISSIONS
+        OWNER_READ OWNER_EXECUTE
+        GROUP_READ GROUP_EXECUTE
+        WORLD_READ
+)
+
+if (UNIX)
+  find_program(STAT_EXECUTABLE NAMES stat)
+  if(NOT STAT_EXECUTABLE)
+    return()
+  endif()
+
+  if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt"
+      OUTPUT_VARIABLE output
+    )
+  elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt"
+      OUTPUT_VARIABLE output
+    )
+  else()
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt"
+      OUTPUT_VARIABLE output
+    )
+  endif()
+
+  if (NOT output EQUAL "554")
+    message(FATAL_ERROR "configure file has different permissions than "
+        "desired, generated permissions: ${output}")
+  endif()
+
+endif()

+ 1 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-stderr.txt

@@ -0,0 +1,5 @@
+CMake Error at SourcePermissionsInvalidArg-1.cmake:1 \(configure_file\):
+  configure_file given both USE_SOURCE_PERMISSIONS and NO_SOURCE_PERMISSIONS.
+  Only one option allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1.cmake

@@ -0,0 +1,5 @@
+configure_file(sourcefile.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+    NO_SOURCE_PERMISSIONS
+    USE_SOURCE_PERMISSIONS
+)

+ 1 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-stderr.txt

@@ -0,0 +1,5 @@
+CMake Error at SourcePermissionsInvalidArg-2.cmake:1 \(configure_file\):
+  configure_file given both FILE_PERMISSIONS and NO_SOURCE_PERMISSIONS.  Only
+  one option allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2.cmake

@@ -0,0 +1,5 @@
+configure_file(sourcefile.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+    NO_SOURCE_PERMISSIONS
+    FILE_PERMISSIONS OWNER_READ
+)

+ 1 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-stderr.txt

@@ -0,0 +1,5 @@
+CMake Error at SourcePermissionsInvalidArg-3.cmake:1 \(configure_file\):
+  configure_file given both FILE_PERMISSIONS and USE_SOURCE_PERMISSIONS.
+  Only one option allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3.cmake

@@ -0,0 +1,5 @@
+configure_file(sourcefile.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+    USE_SOURCE_PERMISSIONS
+    FILE_PERMISSIONS OWNER_READ
+)

+ 1 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-result.txt

@@ -0,0 +1 @@
+1

+ 4 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-stderr.txt

@@ -0,0 +1,4 @@
+CMake Error at SourcePermissionsInvalidArg-4.cmake:1 \(configure_file\):
+  configure_file given FILE_PERMISSIONS without any options.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 4 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4.cmake

@@ -0,0 +1,4 @@
+configure_file(sourcefile.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+    FILE_PERMISSIONS
+)

+ 1 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-result.txt

@@ -0,0 +1 @@
+1

+ 4 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-stderr.txt

@@ -0,0 +1,4 @@
+CMake Error at SourcePermissionsInvalidArg-5.cmake:1 \(configure_file\):
+  configure_file given invalid permission "OWNER_RX","GROUP_RWX".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 0
Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5.cmake

@@ -0,0 +1,6 @@
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt
+    FILE_PERMISSIONS
+        OWNER_READ OWNER_RX
+        GROUP_RWX
+)

+ 40 - 0
Tests/RunCMake/configure_file/UseSourcePermissions.cmake

@@ -0,0 +1,40 @@
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt
+    USE_SOURCE_PERMISSIONS
+)
+
+if (UNIX)
+  find_program(STAT_EXECUTABLE NAMES stat)
+  if(NOT STAT_EXECUTABLE)
+    return()
+  endif()
+
+  if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt"
+      OUTPUT_VARIABLE output1
+    )
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt"
+      OUTPUT_VARIABLE output2
+    )
+  elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt"
+      OUTPUT_VARIABLE output1
+    )
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt"
+      OUTPUT_VARIABLE output2
+    )
+  else()
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt"
+      OUTPUT_VARIABLE output1
+    )
+    execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt"
+      OUTPUT_VARIABLE output2
+    )
+  endif()
+
+  if (NOT output1 EQUAL output2)
+    message(FATAL_ERROR "configure file has different permissions source "
+        "permissions: ${output1} generated permissions: ${output2}")
+  endif()
+
+endif()

+ 1 - 0
Tests/RunCMake/configure_file/sourcefile.txt

@@ -0,0 +1 @@
+an empty file