diff --git a/Help/release/dev/cpack-rpm-default-user-and-group.rst b/Help/release/dev/cpack-rpm-default-user-and-group.rst new file mode 100644 index 000000000..7667c7f23 --- /dev/null +++ b/Help/release/dev/cpack-rpm-default-user-and-group.rst @@ -0,0 +1,9 @@ +cpack-rpm-default-user-and-group +-------------------------------- + +* The "CPackRPM" module learned how to set default values for owning user/group + and file/directory permissions of package content. + See :variable:`CPACK_RPM_DEFAULT_USER`, :variable:`CPACK_RPM_DEFAULT_GROUP`, + :variable:`CPACK_RPM_DEFAULT_FILE_PERMISSIONS`, + :variable:`CPACK_RPM_DEFAULT_DIR_PERMISSIONS` and their per component + counterparts. diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index 7ffec136d..ae51dc103 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -531,6 +531,54 @@ # - /usr/share/doc/.*/man/man.* # - /usr/lib/.*/man/man.* # +# .. variable:: CPACK_RPM_DEFAULT_USER +# CPACK_RPM__DEFAULT_USER +# +# default user ownership of RPM content +# +# * Mandatory : NO +# * Default : root +# +# Value should be user name and not UID. +# Note that must be in upper-case. +# +# .. variable:: CPACK_RPM_DEFAULT_GROUP +# CPACK_RPM__DEFAULT_GROUP +# +# default group ownership of RPM content +# +# * Mandatory : NO +# * Default : root +# +# Value should be group name and not GID. +# Note that must be in upper-case. +# +# .. variable:: CPACK_RPM_DEFAULT_FILE_PERMISSIONS +# CPACK_RPM__DEFAULT_FILE_PERMISSIONS +# +# default permissions used for packaged files +# +# * Mandatory : NO +# * Default : - (system default) +# +# Accepted values are lists with PERMISSIONS. Valid permissions +# are OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, +# GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE and WORLD_EXECUTE. +# Note that must be in upper-case. +# +# .. variable:: CPACK_RPM_DEFAULT_DIR_PERMISSIONS +# CPACK_RPM__DEFAULT_DIR_PERMISSIONS +# +# default permissions used for packaged directories +# +# * Mandatory : NO +# * Default : - (system default) +# +# Accepted values are lists with PERMISSIONS. Valid permissions +# are OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, +# GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE and WORLD_EXECUTE. +# Note that must be in upper-case. +# # Packaging of Symbolic Links # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ # @@ -581,6 +629,35 @@ # Author: Eric Noulard with the help of Alexander Neundorf. +function(get_unix_permissions_octal_notation PERMISSIONS_VAR RETURN_VAR) + set(PERMISSIONS ${${PERMISSIONS_VAR}}) + list(LENGTH PERMISSIONS PERM_LEN_PRE) + list(REMOVE_DUPLICATES PERMISSIONS) + list(LENGTH PERMISSIONS PERM_LEN_POST) + + if(NOT ${PERM_LEN_PRE} EQUAL ${PERM_LEN_POST}) + message(FATAL_ERROR "${PERMISSIONS_VAR} contains duplicate values.") + endif() + + foreach(PERMISSION_TYPE "OWNER" "GROUP" "WORLD") + set(${PERMISSION_TYPE}_PERMISSIONS 0) + + foreach(PERMISSION ${PERMISSIONS}) + if("${PERMISSION}" STREQUAL "${PERMISSION_TYPE}_READ") + math(EXPR ${PERMISSION_TYPE}_PERMISSIONS "${${PERMISSION_TYPE}_PERMISSIONS} + 4") + elseif("${PERMISSION}" STREQUAL "${PERMISSION_TYPE}_WRITE") + math(EXPR ${PERMISSION_TYPE}_PERMISSIONS "${${PERMISSION_TYPE}_PERMISSIONS} + 2") + elseif("${PERMISSION}" STREQUAL "${PERMISSION_TYPE}_EXECUTE") + math(EXPR ${PERMISSION_TYPE}_PERMISSIONS "${${PERMISSION_TYPE}_PERMISSIONS} + 1") + elseif(PERMISSION MATCHES "${PERMISSION_TYPE}.*") + message(FATAL_ERROR "${PERMISSIONS_VAR} contains invalid values.") + endif() + endforeach() + endforeach() + + set(${RETURN_VAR} "${OWNER_PERMISSIONS}${GROUP_PERMISSIONS}${WORLD_PERMISSIONS}" PARENT_SCOPE) +endfunction() + function(cpack_rpm_prepare_relocation_paths) # set appropriate prefix, remove possible trailing slash and convert backslashes to slashes if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX) @@ -1572,6 +1649,30 @@ function(cpack_rpm_generate_package) "${CPACK_RPM_PACKAGE_RELOCATABLE}" ) + # set default user and group + foreach(_PERM_TYPE "USER" "GROUP") + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}) + set(TMP_DEFAULT_${_PERM_TYPE} "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}}") + elseif(CPACK_RPM_DEFAULT_${_PERM_TYPE}) + set(TMP_DEFAULT_${_PERM_TYPE} "${CPACK_RPM_DEFAULT_${_PERM_TYPE}}") + else() + set(TMP_DEFAULT_${_PERM_TYPE} "root") + endif() + endforeach() + + # set default file and dir permissions + foreach(_PERM_TYPE "FILE" "DIR") + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS) + get_unix_permissions_octal_notation("CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS" "TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS") + set(_PERMISSIONS_VAR "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS") + elseif(CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS) + get_unix_permissions_octal_notation("CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS" "TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS") + set(_PERMISSIONS_VAR "CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS") + else() + set(TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS "-") + endif() + endforeach() + # The name of the final spec file to be used by rpmbuild set(CPACK_RPM_BINARY_SPECFILE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_NAME}.spec") @@ -1671,7 +1772,7 @@ mv \"\@CPACK_TOPLEVEL_DIRECTORY\@/tmpBBroot\" $RPM_BUILD_ROOT \@CPACK_RPM_SPEC_PREUNINSTALL\@ %files -%defattr(-,root,root,-) +%defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@) \@CPACK_RPM_INSTALL_FILES\@ \@CPACK_RPM_ABSOLUTE_INSTALL_FILES\@ \@CPACK_RPM_USER_INSTALL_FILES\@ diff --git a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in index 0f2b774c8..0ffe44d3a 100644 --- a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in +++ b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in @@ -32,6 +32,20 @@ if(CPACK_GENERATOR MATCHES "RPM") # test package do not use CPACK_PACKAGING_INSTALL_PREFIX # as relocation path set(CPACK_RPM_NO_LIBRARIES_INSTALL_PREFIX_RELOCATION true) + + # test default permissions + set(CPACK_RPM_DEFAULT_USER defusr) + set(CPACK_RPM_DEFAULT_GROUP defgrp) + set(CPACK_RPM_DEFAULT_FILE_PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ) + set(CPACK_RPM_DEFAULT_DIR_PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ) + set(CPACK_RPM_LIBRARIES_DEFAULT_USER user) + set(CPACK_RPM_APPLICATIONS_DEFAULT_GROUP group) + set(CPACK_RPM_LIBRARIES_DEFAULT_FILE_PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE) + set(CPACK_RPM_APPLICATIONS_DEFAULT_DIR_PERMISSIONS + OWNER_READ GROUP_READ WORLD_READ) endif() if(CPACK_GENERATOR MATCHES "DEB") diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake index 34b9c8251..0c5cca82d 100644 --- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake @@ -304,6 +304,30 @@ if(CPackGen MATCHES "RPM") message(FATAL_ERROR "error: '${check_file}' rpm package content does not match expected value - regex '${check_content_list}'; RPM output: '${check_package_content}'; generated spec file: '${spec_file_content}'") endif() + + # validate permissions user and group + execute_process(COMMAND ${RPM_EXECUTABLE} -pqlv ${check_file} + OUTPUT_VARIABLE check_file_content + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(check_file_libraries_match) + set(check_file_match_expected_permissions ".*-rwx------.*user.*defgrp.*") + elseif(check_file_headers_match) + set(check_file_match_expected_permissions ".*-rwxr--r--.*defusr.*defgrp.*") + elseif(check_file_applications_match) + set(check_file_match_expected_permissions ".*-rwxr--r--.*defusr.*group.*") + elseif(check_file_Unspecified_match) + set(check_file_match_expected_permissions ".*-rwxr--r--.*defusr.*defgrp.*") + else() + message(FATAL_ERROR "error: unexpected rpm package '${check_file}'") + endif() + + string(REGEX MATCH "${check_file_match_expected_permissions}" check_file_match_permissions "${check_file_content}") + + if(NOT check_file_match_permissions) + message(FATAL_ERROR "error: '${check_file}' rpm package permissions do not match expected value - regex '${check_file_match_expected_permissions}'") + endif() endforeach() #######################