Browse Source

CPack/Archive: Add support for setting UID/GID in archive

Add `CPACK_ARCHIVE_UID` and `CPACK_ARCHIVE_GID` options.

Add a policy to change the default to 0/0 to enable ownership
by root if unpacking as root.

Fixes: #12901
Clinton Stimpson 3 weeks ago
parent
commit
5a18728cec

+ 18 - 0
Help/cpack_gen/archive.rst

@@ -100,6 +100,24 @@ Variables specific to CPack Archive generator
   If enabled (``ON``) multiple packages are generated. By default a single package
   containing files of all components is generated.
 
+.. variable:: CPACK_ARCHIVE_UID
+
+  .. versionadded: 4.3
+
+  Set the UID of entries contained in the archive.
+  Specify ``-1`` to use the UID of the current user.
+
+  :Default: ``0`` (see policy :policy:`CMP0206`)
+
+.. variable:: CPACK_ARCHIVE_GID
+
+  .. versionadded: 4.3
+
+  Set the GID of entries contained in the archive.
+  Specify ``-1`` to use the GID of the current user.
+
+  :Default: ``0`` (see policy :policy:`CMP0206`)
+
 Variables used by CPack Archive generator
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

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

@@ -98,6 +98,7 @@ Policies Introduced by CMake 4.3
 .. toctree::
    :maxdepth: 1
 
+   CMP0206: The CPack Archive Generator defaults to UID 0 and GID 0. </policy/CMP0206>
    CMP0205: file(CREATE_LINK) with COPY_ON_ERROR copies directory content. </policy/CMP0205>
 
 Policies Introduced by CMake 4.2

+ 30 - 0
Help/policy/CMP0206.rst

@@ -0,0 +1,30 @@
+CMP0206
+-------
+
+.. versionadded:: 4.3
+
+The :cpack_gen:`CPack Archive Generator` defaults to UID 0 and GID 0.
+
+In CMake 4.2 and below, the :cpack_gen:`CPack Archive Generator` always used
+the current user's UID/GID in archive entries.  CMake 4.3 added the
+:variable:`CPACK_ARCHIVE_UID` and :variable:`CPACK_ARCHIVE_GID` variables
+to control them.  If either is set, the default for the other is ``0``.
+If neither is set, CMake 4.3 and above prefer to default both UID and GID
+to ``0`` so that unpacking by ``root`` produces paths owned by ``root``.
+This policy provides compatibility with projects that have not been updated
+to expect the new behavior.
+
+The ``OLD`` behavior for this policy is to produce archive entries with
+the current user's UID/GID by default.
+The ``NEW`` behavior for this policy is to produce archive entries with
+the UID/GID set to 0/0 by default.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.3
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: include/STANDARD_ADVICE.rst
+
+See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0206 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
+
+.. include:: include/DEPRECATED.rst

+ 7 - 0
Help/release/dev/cpack-archive-ownership.rst

@@ -0,0 +1,7 @@
+cpack-archive-ownership
+-----------------------
+
+* The :cpack_gen:`CPack Archive Generator` generator gained new
+  :variable:`CPACK_ARCHIVE_UID` and :variable:`CPACK_ARCHIVE_GID`
+  options to specify the UID and GID of archive entries.
+  The default now UID 0 and GID 0.  See policy :policy:`CMP0206`.

+ 2 - 0
Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst

@@ -40,6 +40,8 @@ only for the policies that do not warn by default:
   policy :policy:`CMP0133`.
 * ``CMAKE_POLICY_WARNING_CMP0172`` controls the warning for
   policy :policy:`CMP0172`.
+* ``CMAKE_POLICY_WARNING_CMP0206`` controls the warning for
+  policy :policy:`CMP0206`.
 
 This variable should not be set by a project in CMake code.  Project
 developers running CMake may set this variable in their cache to

+ 18 - 0
Modules/CPack.cmake

@@ -936,6 +936,24 @@ elseif(APPLE AND CPACK_BINARY_PRODUCTBUILD AND
 endif()
 unset(_CPack_CMP0161)
 
+# Archive specific variables
+if(NOT DEFINED CPACK_ARCHIVE_UID AND NOT DEFINED CPACK_ARCHIVE_GID)
+  cmake_policy(GET CMP0206 _CPack_CMP0206)
+  if(NOT "x${_CPack_CMP0206}x" STREQUAL "xNEWx")
+    if(NOT "x${_CPack_CMP0206}x" STREQUAL "xOLDx" AND CMAKE_POLICY_WARNING_CMP0206)
+      cmake_policy(GET_WARNING CMP0206 _CMP0206_warning)
+      message(AUTHOR_WARNING
+        "${_CMP0206_warning}\n"
+        "For compatibility, CMake will set archive UID/GID to -1/-1."
+        )
+      unset(_CMP0206_warning)
+    endif()
+    _cpack_set_default(CPACK_ARCHIVE_UID "-1")
+    _cpack_set_default(CPACK_ARCHIVE_GID "-1")
+  endif()
+  unset(_CPack_CMP0206)
+endif()
+
 # set sysroot so SDK tools can be used
 if(CMAKE_OSX_SYSROOT)
   _cpack_set_default(CPACK_OSX_SYSROOT "${_CMAKE_OSX_SYSROOT_PATH}")

+ 16 - 0
Source/CPack/cmCPackArchiveGenerator.cxx

@@ -318,6 +318,9 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
   }                                                                           \
   cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat, 0,          \
                          this->GetThreadCount());                             \
+  if (this->UID >= 0 && this->GID >= 0) {                                     \
+    archive.SetUIDAndGID(this->UID, this->GID);                               \
+  }                                                                           \
   do {                                                                        \
     if (!archive.Open()) {                                                    \
       cmCPackLogger(cmCPackLog::LOG_ERROR,                                    \
@@ -436,6 +439,19 @@ int cmCPackArchiveGenerator::PackageFiles()
   cmCPackLogger(cmCPackLog::LOG_DEBUG,
                 "Toplevel: " << this->toplevel << std::endl);
 
+  if (cmValue UIDoption = this->GetOptionIfSet("CPACK_ARCHIVE_UID")) {
+    long u;
+    if (cmStrToLong(*UIDoption, &u)) {
+      this->UID = static_cast<int>(u);
+    }
+  }
+  if (cmValue GIDoption = this->GetOptionIfSet("CPACK_ARCHIVE_GID")) {
+    long g;
+    if (cmStrToLong(*GIDoption, &g)) {
+      this->GID = static_cast<int>(g);
+    }
+  }
+
   if (this->WantsComponentInstallation()) {
     // CASE 1 : COMPONENT ALL-IN-ONE package
     // If ALL COMPONENTS in ONE package has been requested

+ 2 - 0
Source/CPack/cmCPackArchiveGenerator.h

@@ -97,4 +97,6 @@ private:
   cmArchiveWrite::Compress Compress;
   std::string ArchiveFormat;
   std::string OutputExtension;
+  int UID = 0;
+  int GID = 0;
 };

+ 4 - 1
Source/cmPolicies.h

@@ -615,7 +615,10 @@ class cmMakefile;
          2, 0, WARN)                                                          \
   SELECT(POLICY, CMP0205,                                                     \
          "file(CREATE_LINK) with COPY_ON_ERROR copies directory content.", 4, \
-         3, 0, WARN)
+         3, 0, WARN)                                                          \
+  SELECT(POLICY, CMP0206,                                                     \
+         "The CPack Archive Generator defaults to UID 0 and GID 0.", 4, 3, 0, \
+         WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \

+ 3 - 0
Tests/RunCMake/CPackConfig/CMP0206-NEW-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+test_variable(CPACK_ARCHIVE_UID "")
+test_variable(CPACK_ARCHIVE_GID "")

+ 1 - 0
Tests/RunCMake/CPackConfig/CMP0206-NEW.cmake

@@ -0,0 +1 @@
+cmake_policy(SET CMP0206 NEW)

+ 3 - 0
Tests/RunCMake/CPackConfig/CMP0206-OLD-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+test_variable(CPACK_ARCHIVE_UID "-1")
+test_variable(CPACK_ARCHIVE_GID "-1")

+ 2 - 0
Tests/RunCMake/CPackConfig/CMP0206-OLD.cmake

@@ -0,0 +1,2 @@
+set(CMAKE_POLICY_WARNING_CMP0206 1)
+cmake_policy(SET CMP0206 OLD)

+ 3 - 0
Tests/RunCMake/CPackConfig/CMP0206-WARN-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+test_variable(CPACK_ARCHIVE_UID "-1")
+test_variable(CPACK_ARCHIVE_GID "-1")

+ 10 - 0
Tests/RunCMake/CPackConfig/CMP0206-WARN-stderr.txt

@@ -0,0 +1,10 @@
+^CMake Warning \(dev\) at [^
+]*/Modules/CPack\.cmake:[0-9]+ \(message\):
+  Policy CMP0206 is not set: The CPack Archive Generator defaults to UID 0
+  and GID 0\.  Run "cmake --help-policy CMP0206" for policy details\.  Use the
+  cmake_policy command to set the policy and suppress this warning\.
+
+  For compatibility, CMake will set archive UID/GID to -1/-1\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.$

+ 1 - 0
Tests/RunCMake/CPackConfig/CMP0206-WARN.cmake

@@ -0,0 +1 @@
+set(CMAKE_POLICY_WARNING_CMP0206 1)

+ 3 - 0
Tests/RunCMake/CPackConfig/RunCMakeTest.cmake

@@ -8,6 +8,9 @@ run_cmake(CMP0161-WARN)
 run_cmake(CMP0172-NEW)
 run_cmake(CMP0172-OLD)
 run_cmake(CMP0172-WARN)
+run_cmake(CMP0206-NEW)
+run_cmake(CMP0206-OLD)
+run_cmake(CMP0206-WARN)
 run_cmake(Simple)
 run_cmake(Default)
 run_cmake(Special)