Commit 7e896029 authored by Domen Vrankar's avatar Domen Vrankar

CPack: enable setting default dir creation permissions

Introduces CPACK_DEFAULT_DIRECTORY_INSTALL_PERMISSIONS
variable which adds support for functionality introduced
by CMAKE_DEFAULT_DIRECTORY_INSTALL_PERMISSIONS variable.

Fixes #17333

# Conflicts:
#	Help/release/dev/cmake-default-dir-install-permissions.rst
parent a4c82916
......@@ -530,6 +530,7 @@ Variables for CPack
/variable/CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
/variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
/variable/CPACK_INCLUDE_TOPLEVEL_DIRECTORY
/variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
/variable/CPACK_INSTALL_SCRIPT
/variable/CPACK_PACKAGING_INSTALL_PREFIX
/variable/CPACK_SET_DESTDIR
......
......@@ -5,3 +5,8 @@ cmake-default-dir-install-permissions
to enable setting of default permissions for directories created implicitly
during installation of files by :command:`install` and
:command:`file(INSTALL)`.
* The :variable:`CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable was added
which serves the same purpose during packaging as the
:variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable serves during
installation (e.g. ``make install``).
CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
-------------------------------------------
Default permissions for implicitly created directories during packaging.
This variable serves the same purpose during packaging as the
:variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable
serves during installation (e.g. ``make install``).
If `include(CPack)` is used then by default this variable is set to the content
of :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`.
......@@ -384,6 +384,12 @@ _cpack_set_default(CPACK_RESOURCE_FILE_WELCOME
_cpack_set_default(CPACK_MODULE_PATH "${CMAKE_MODULE_PATH}")
# Set default directory creation permissions mode
if(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)
_cpack_set_default(CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
"${CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS}")
endif()
if(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL)
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
endif()
......
......@@ -12,6 +12,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmCryptoHash.h"
#include "cmFSPermissions.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
......@@ -201,6 +202,29 @@ int cmCPackGenerator::InstallProject()
cmSystemTools::PutEnv("DESTDIR=");
}
// prepare default created directory permissions
mode_t default_dir_mode_v = 0;
mode_t* default_dir_mode = nullptr;
const char* default_dir_install_permissions =
this->GetOption("CPACK_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 (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Invalid permission value '"
<< arg
<< "'."
" CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
"value is invalid."
<< std::endl);
return 0;
}
}
default_dir_mode = &default_dir_mode_v;
}
// If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them
// as listed
if (!this->InstallProjectViaInstallCommands(setDestDir,
......@@ -218,15 +242,15 @@ int cmCPackGenerator::InstallProject()
// If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES
// then glob it and copy it to CPACK_TEMPORARY_DIRECTORY
// This is used in Source packaging
if (!this->InstallProjectViaInstalledDirectories(setDestDir,
tempInstallDirectory)) {
if (!this->InstallProjectViaInstalledDirectories(
setDestDir, tempInstallDirectory, default_dir_mode)) {
return 0;
}
// If the project is a CMAKE project then run pre-install
// and then read the cmake_install script to run it
if (!this->InstallProjectViaInstallCMakeProjects(setDestDir,
bareTempInstallDirectory)) {
if (!this->InstallProjectViaInstallCMakeProjects(
setDestDir, bareTempInstallDirectory, default_dir_mode)) {
return 0;
}
......@@ -274,7 +298,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
}
int cmCPackGenerator::InstallProjectViaInstalledDirectories(
bool setDestDir, const std::string& tempInstallDirectory)
bool setDestDir, const std::string& tempInstallDirectory,
const mode_t* default_dir_mode)
{
(void)setDestDir;
(void)tempInstallDirectory;
......@@ -385,7 +410,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
// make sure directory exists for symlink
std::string destDir =
cmSystemTools::GetFilenamePath(symlinked.second);
if (!destDir.empty() && !cmSystemTools::MakeDirectory(destDir)) {
if (!destDir.empty() &&
!cmSystemTools::MakeDirectory(destDir, default_dir_mode)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: "
<< destDir << "\nTrying to create symlink: "
<< symlinked.second << "--> " << symlinked.first
......@@ -464,7 +490,8 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
}
int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
bool setDestDir, const std::string& baseTempInstallDirectory)
bool setDestDir, const std::string& baseTempInstallDirectory,
const mode_t* default_dir_mode)
{
const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
......@@ -631,6 +658,13 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
}
}
const char* default_dir_inst_permissions =
this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
if (default_dir_inst_permissions && *default_dir_inst_permissions) {
mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
default_dir_inst_permissions);
}
if (!setDestDir) {
tempInstallDirectory += this->GetPackagingInstallPrefix();
}
......@@ -690,7 +724,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '"
<< dir << "'" << std::endl);
if (!cmsys::SystemTools::MakeDirectory(dir.c_str())) {
if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: " << dir << std::endl);
......@@ -700,8 +734,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
mf.AddDefinition("CMAKE_INSTALL_PREFIX",
tempInstallDirectory.c_str());
if (!cmsys::SystemTools::MakeDirectory(
tempInstallDirectory.c_str())) {
if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
default_dir_mode)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< tempInstallDirectory << std::endl);
......
......@@ -12,6 +12,7 @@
#include "cmCPackComponentGroup.h"
#include "cmSystemTools.h"
#include "cm_sys_stat.h"
class cmCPackLog;
class cmInstalledFile;
......@@ -168,9 +169,11 @@ protected:
virtual int InstallProjectViaInstallScript(
bool setDestDir, const std::string& tempInstallDirectory);
virtual int InstallProjectViaInstalledDirectories(
bool setDestDir, const std::string& tempInstallDirectory);
bool setDestDir, const std::string& tempInstallDirectory,
const mode_t* default_dir_mode);
virtual int InstallProjectViaInstallCMakeProjects(
bool setDestDir, const std::string& tempInstallDirectory);
bool setDestDir, const std::string& tempInstallDirectory,
const mode_t* default_dir_mode);
/**
* The various level of support of
......
......@@ -7,6 +7,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake")
run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM" false "MONOLITHIC;COMPONENT")
run_cpack_test(CUSTOM_NAMES "RPM;DEB;TGZ" true "COMPONENT")
run_cpack_test(DEBUGINFO "RPM" true "COMPONENT")
run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM;DEB" false "MONOLITHIC;COMPONENT")
run_cpack_test(DEPENDENCIES "RPM;DEB" true "COMPONENT")
run_cpack_test(DIST "RPM" false "MONOLITHIC")
run_cpack_test(EMPTY_DIR "RPM;DEB;TGZ" true "MONOLITHIC;COMPONENT")
......
if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_.*_var")
set(EXPECTED_FILES_COUNT "0")
else()
set(EXPECTED_FILES_COUNT "1")
set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
endif()
if(NOT ${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_.*_var")
if(GENERATOR_TYPE STREQUAL "RPM")
function(checkContentPermissions_ FILE REGEX)
execute_process(COMMAND ${RPM_EXECUTABLE} -qp --dump ${FILE}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE PERMISSIONS_
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT PERMISSIONS_ MATCHES "${REGEX}")
message(FATAL_ERROR "Permissions in '${FILE}'. Permissions: '${PERMISSIONS_}'")
endif()
endfunction()
if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CMAKE_var_set")
checkContentPermissions_("${FOUND_FILE_1}"
"/usr/foo .*740 root root.*")
else()
checkContentPermissions_("${FOUND_FILE_1}"
"/usr/foo .*700 root root.*")
endif()
else() # DEB
function(checkContentPermissions_ FILE REGEX)
getPackageContent("${FILE}" PERMISSIONS_)
if(NOT PERMISSIONS_ MATCHES "${REGEX}")
message(FATAL_ERROR "Permissions in '${FILE}'. Permissions: '${PERMISSIONS_}'")
endif()
endfunction()
if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CMAKE_var_set")
checkContentPermissions_("${FOUND_FILE_1}"
"drwxr----- root/root .* ./usr/\ndrwxr----- root/root .* ./usr/foo/\n.*")
else()
checkContentPermissions_("${FOUND_FILE_1}"
"drwx------ root/root .* ./usr/\ndrwx------ root/root .* ./usr/foo/\n.*")
endif()
endif()
endif()
.*CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS value is invalid.*
.*CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS value is invalid.*
if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CMAKE_var_set" OR
${RunCMake_SUBTEST_SUFFIX} MATCHES "both_set")
set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
OWNER_READ
OWNER_WRITE
OWNER_EXECUTE
GROUP_READ
)
endif()
if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_CMAKE_var")
list(APPEND CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "INVALID")
endif()
if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CPACK_var_set" OR
${RunCMake_SUBTEST_SUFFIX} MATCHES "both_set")
set(CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
OWNER_READ
OWNER_WRITE
OWNER_EXECUTE
)
endif()
if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_CPACK_var")
list(APPEND CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "INVALID")
endif()
install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
if(PACKAGING_TYPE STREQUAL "COMPONENT")
set(CPACK_COMPONENTS_ALL test)
endif()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment