Browse Source

CMake: enable setting default dir creation permissions

Introduces CMAKE_DEFAULT_DIRECTORY_INSTALL_PERMISSIONS
variable which enables the user to specify the default
permissions for directory creation. This setting is then
used to auto set the permissions on directories which
are implicitly created by install() and file(INSTALL)
commands such as CMAKE_INSTALL_PREFIX directories.
Domen Vrankar 8 years ago
parent
commit
deeba85f81

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -159,6 +159,7 @@ Variables that Change Behavior
    /variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
    /variable/CMAKE_INCLUDE_PATH
    /variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME
+   /variable/CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
    /variable/CMAKE_INSTALL_MESSAGE
    /variable/CMAKE_INSTALL_PREFIX
    /variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT

+ 7 - 0
Help/release/dev/cmake-default-dir-install-permissions.rst

@@ -0,0 +1,7 @@
+cmake-default-dir-install-permissions
+-------------------------------------
+
+* The :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable was added
+  to enable setting of default permissions for directories created implicitly
+  during installation of files by :command:`install` and
+  :command:`file(INSTALL)`.

+ 29 - 0
Help/variable/CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS.rst

@@ -0,0 +1,29 @@
+CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+-------------------------------------------
+
+Default permissions for directories created implicitly during installation
+of files by :command:`install` and :command:`file(INSTALL)`.
+
+If ``make install`` is invoked and directories are implicitly created they
+get permissions set by :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`
+variable or platform specific default permissions if the variable is not set.
+
+Implicitly created directories are created if they are not explicitly installed
+by :command:`install` command but are needed to install a file on a certain
+path. Example of such locations are directories created due to the setting of
+:variable:`CMAKE_INSTALL_PREFIX`.
+
+Expected content of the :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`
+variable is a list of permissions that can be used by :command:`install` command
+`PERMISSIONS` section.
+
+Example usage:
+
+::
+
+ set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+      OWNER_READ
+      OWNER_WRITE
+      OWNER_EXECUTE
+      GROUP_READ
+    )

+ 22 - 1
Source/cmFileCommand.cxx

@@ -2015,9 +2015,30 @@ bool cmFileInstaller::HandleInstallDestination()
     this->DestDirLength = int(sdestdir.size());
   }
 
+  // check if default dir creation permissions were set
+  mode_t default_dir_mode_v = 0;
+  mode_t* default_dir_mode = nullptr;
+  const char* default_dir_install_permissions = this->Makefile->GetDefinition(
+    "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+  if (default_dir_install_permissions && *default_dir_install_permissions) {
+    std::vector<std::string> items;
+    cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
+    for (const auto& arg : items) {
+      if (!this->CheckPermissions(arg, default_dir_mode_v)) {
+        std::ostringstream e;
+        e << this->FileCommand->GetError()
+          << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.";
+        this->FileCommand->SetError(e.str());
+        return false;
+      }
+    }
+
+    default_dir_mode = &default_dir_mode_v;
+  }
+
   if (this->InstallType != cmInstallType_DIRECTORY) {
     if (!cmSystemTools::FileExists(destination.c_str())) {
-      if (!cmSystemTools::MakeDirectory(destination.c_str())) {
+      if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
         std::string errstring = "cannot create directory: " + destination +
           ". Maybe need administrative privileges.";
         this->FileCommand->SetError(errstring);

+ 14 - 0
Source/cmLocalGenerator.cxx

@@ -487,6 +487,20 @@ void cmLocalGenerator::GenerateInstallRules()
     /* clang-format on */
   }
 
+  // Write default directory permissions.
+  if (const char* defaultDirPermissions = this->Makefile->GetDefinition(
+        "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) {
+    /* clang-format off */
+    fout <<
+      "# Set default install directory permissions.\n"
+      "if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)\n"
+      "  set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS \""
+         << defaultDirPermissions << "\")\n"
+      "endif()\n"
+      "\n";
+    /* clang-format on */
+  }
+
   // Ask each install generator to write its code.
   std::vector<cmInstallGenerator*> const& installers =
     this->Makefile->GetInstallGenerators();