Hi Brad and Domen,

This is a follow up of the following thread

http://public.kitware.com/pipermail/cmake-developers/2015-August/026125.html

I have made the following changes in order to:
- support the UID/GID/UNAME/GNAME and permission on tar files at creation time
- using directly libarchive in CPackDeb
- removing completely the need of fakeroot

Please review the patches (mainly 2, the other one is just a typo fix).
Or if you prefer I can just create a topic. The patches are based on master and are quite orthogonal.

Is it on time for 3.4 freeze?

Thanks!
Raffi
From 2f12e427c4ffe238fbf79d7c317c90b4d9c3131f Mon Sep 17 00:00:00 2001
From: Raffi Enficiaud <raffi.enfici...@mines-paris.org>
Date: Tue, 8 Sep 2015 23:09:01 +0200
Subject: [PATCH 1/3] Various typo fixes RunCMake.CPack: Making the error
 message somehow more readable

---
 Source/cmGeneratedFileStream.h          | 4 ++--
 Tests/RunCMake/CPack/DEB/Helpers.cmake  | 2 +-
 Tests/RunCMake/CPack/README.txt         | 4 ++--
 Tests/RunCMake/CPack/VerifyResult.cmake | 7 ++++---
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h
index 2aa6beb..8df3e1a 100644
--- a/Source/cmGeneratedFileStream.h
+++ b/Source/cmGeneratedFileStream.h
@@ -56,10 +56,10 @@ protected:
   // Whether the real file stream was valid when it was closed.
   bool Okay;
 
-  // Whether the destionation file is compressed
+  // Whether the destination file is compressed
   bool Compress;
 
-  // Whether the destionation file is compressed
+  // Whether the destination file is compressed
   bool CompressExtraExtension;
 };
 
diff --git a/Tests/RunCMake/CPack/DEB/Helpers.cmake 
b/Tests/RunCMake/CPack/DEB/Helpers.cmake
index a204a3c..b6f113b 100644
--- a/Tests/RunCMake/CPack/DEB/Helpers.cmake
+++ b/Tests/RunCMake/CPack/DEB/Helpers.cmake
@@ -14,7 +14,7 @@ function(verifyDebControl FILE PREFIX VERIFY_FILES)
           ERROR_VARIABLE err_)
 
   if(err_)
-    message(FATAL_ERROR "Debian controll verification failed for file: "
+    message(FATAL_ERROR "Debian control verification failed for file: "
         "'${FILE}'; error output: '${err_}'")
   endif()
 
diff --git a/Tests/RunCMake/CPack/README.txt b/Tests/RunCMake/CPack/README.txt
index 365c737..ea68304 100644
--- a/Tests/RunCMake/CPack/README.txt
+++ b/Tests/RunCMake/CPack/README.txt
@@ -32,14 +32,14 @@ different types of packages. This script is placed into 
CPack test root
 directory even if it will be used for only one of the generators.
 
 If test will be used for multiple generators but some of them require some
-generator speciffic commands then those commands should be added to a separate
+generator specific commands then those commands should be added to a separate
 file that should be located in '<generator_name>/<test_name>-specifics.cmake'
 in CPack test root directory.
 
 CPack execution phase:
 ----------------------
 
-Only exececutes CPack for content that was generated during CMake execution
+Only executes CPack for content that was generated during CMake execution
 phase.
 
 Verification of generated files:
diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake 
b/Tests/RunCMake/CPack/VerifyResult.cmake
index 96efa9e..6eab531 100644
--- a/Tests/RunCMake/CPack/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/VerifyResult.cmake
@@ -28,8 +28,9 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0)
 
       if(NOT expected_content_list)
         message(FATAL_ERROR
-          "Unexpected file content for file No. '${file_no_}'!"
-          " Content: '${PACKAGE_CONTENT}'"
+          "Unexpected file content for file No. '${file_no_}'!\n"
+          " Content: '${PACKAGE_CONTENT}'\n\n"
+          " Expected: '${EXPECTED_FILE_CONTENT_${file_no_}}'"
           "${output_error_message}")
       endif()
     else()
@@ -56,7 +57,7 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0)
         "${output_error_message}")
   endif()
 
-  # sanity check that we didn't accidentaly list wrong files with our regular
+  # sanity check that we didn't accidentally list wrong files with our regular
   # expressions
   foreach(expected_ IN LISTS allFoundFiles_)
     list(FIND foundFiles_ "${expected_}" found_)
-- 
2.0.1

From ba086d51479b7d5d11652d3647e5f4775d0a4f7d Mon Sep 17 00:00:00 2001
From: Raffi Enficiaud <raffi.enfici...@mines-paris.org>
Date: Fri, 11 Sep 2015 16:00:28 +0200
Subject: [PATCH 2/3] cmArchiveWrite: user/group and permissions

- support for UID/GID and UNAME/GNAME
- support for permission and permission mask
- support for non-recursive folder adding
---
 Source/cmArchiveWrite.cxx | 45 ++++++++++++++++++++++++---
 Source/cmArchiveWrite.h   | 77 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 9f56324..a8fc85d 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -84,7 +84,11 @@ cmArchiveWrite::cmArchiveWrite(
     Archive(archive_write_new()),
     Disk(archive_read_disk_new()),
     Verbose(false),
-    Format(format)
+    Format(format),
+    uid(-1),
+    gid(-1),
+    permissions(-1),
+    permissionsMask(-1)
 {
   switch (c)
     {
@@ -181,7 +185,10 @@ cmArchiveWrite::~cmArchiveWrite()
 }
 
 //----------------------------------------------------------------------------
-bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix)
+bool cmArchiveWrite::Add(std::string path,
+                         size_t skip,
+                         const char* prefix,
+                         bool recursive)
 {
   if(this->Okay())
     {
@@ -189,20 +196,21 @@ bool cmArchiveWrite::Add(std::string path, size_t skip, 
const char* prefix)
       {
       path.erase(path.size()-1);
       }
-    this->AddPath(path.c_str(), skip, prefix);
+    this->AddPath(path.c_str(), skip, prefix, recursive);
     }
   return this->Okay();
 }
 
 //----------------------------------------------------------------------------
 bool cmArchiveWrite::AddPath(const char* path,
-                             size_t skip, const char* prefix)
+                             size_t skip, const char* prefix,
+                             bool recursive)
 {
   if(!this->AddFile(path, skip, prefix))
     {
     return false;
     }
-  if(!cmSystemTools::FileIsDirectory(path) ||
+  if((!cmSystemTools::FileIsDirectory(path) || !recursive) ||
     cmSystemTools::FileIsSymlink(path))
     {
     return true;
@@ -278,6 +286,33 @@ bool cmArchiveWrite::AddFile(const char* file,
       }
     archive_entry_set_mtime(e, t, 0);
     }
+
+  // manages the uid/guid of the entry (if any)
+  if (this->uid > -1 && this->gid > -1)
+    {
+      archive_entry_set_uid(e, this->uid);
+      archive_entry_set_gid(e, this->gid);
+    }
+
+  if (this->uname.size() && this->gname.size())
+    {
+      archive_entry_set_uname(e, this->uname.c_str());
+      archive_entry_set_gname(e, this->gname.c_str());
+    }
+
+
+  // manages the permissions
+  if (this->permissions > -1)
+    {
+      archive_entry_set_perm(e, this->permissions);
+    }
+
+  if (this->permissionsMask > -1)
+  {
+    mode_t perm = archive_entry_filetype(e);
+    archive_entry_set_perm(e, perm & this->permissionsMask );
+  }
+
   // Clear acl and xattr fields not useful for distribution.
   archive_entry_acl_clear(e);
   archive_entry_xattr_clear(e);
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index e6f515d..353dfe8 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -52,7 +52,10 @@ public:
    * skip.  The remaining part of the input path is appended to the
    * "prefix" value to construct the final name in the archive.
    */
-  bool Add(std::string path, size_t skip = 0, const char* prefix = 0);
+  bool Add(std::string path,
+     size_t skip = 0,
+     const char* prefix = 0,
+     bool recursive = true);
 
   /** Returns true if there has been no error.  */
   operator safe_bool() const
@@ -69,9 +72,61 @@ public:
   void SetVerbose(bool v) { this->Verbose = v; }
 
   void SetMTime(std::string const& t) { this->MTime = t; }
+
+
+  //! Sets the permissions of the added files/folders
+  //! @note set to -1 to use the default permissions
+  long int SetPermissions(long int permissions_)
+  {
+    std::swap(this->permissions, permissions_);
+    return permissions_;
+  }
+
+  //! Sets the permissions mask of the files/folders
+  //!
+  //! The permissions will be copied from the existing file
+  //! or folder. The mask will then be applied to unset
+  //! some of them
+  long int SetPermissionsMask(long int permissionsMask_)
+  {
+    std::swap(this->permissionsMask, permissionsMask_);
+    return permissionsMask_;
+  }
+
+  //! Sets the UID to be used in the tar file
+  //! @return the previous UID
+  //! @note set to -1 to disable the UID overriding
+  long int SetUID( long int uid_ )
+  {
+    std::swap(this->uid, uid_);
+    return uid_;
+
+  }
+
+  std::string SetUNAME(std::string uname_)
+  {
+    std::swap(this->uname, uname_);
+    return uname_;
+  }
+
+  //! Sets the UID to be used in the tar file
+  //! @return the previous UID
+  long int SetGID( long int gid_ )
+  {
+    std::swap(this->gid, gid_);
+    return gid_;
+  }
+
+  std::string SetGNAME(std::string gname_)
+  {
+    std::swap(this->gname, gname_);
+    return gname_;
+  }
+
 private:
   bool Okay() const { return this->Error.empty(); }
-  bool AddPath(const char* path, size_t skip, const char* prefix);
+  bool AddPath(const char* path, size_t skip, const char* prefix,
+               bool recursive = true);
   bool AddFile(const char* file, size_t skip, const char* prefix);
   bool AddData(const char* file, size_t size);
 
@@ -87,6 +142,24 @@ private:
   std::string Format;
   std::string Error;
   std::string MTime;
+
+  //! UID of the user in the tar file. Set to -1
+  //! to disable overriding
+  long int uid;
+
+  //! GUID of the user in the tar file
+  long int gid;
+
+  //! UNAME/GNAME of the user (doies not override UID/GID)
+  //!@{
+  std::string uname;
+  std::string gname;
+  //!@}
+
+
+  //! Permissions on the files/folders
+  long int permissions;
+  long int permissionsMask;
 };
 
 #endif
-- 
2.0.1

From 02d58d1bb81e7bbdee6d0ef9a8674b8d0c914126 Mon Sep 17 00:00:00 2001
From: Raffi Enficiaud <raffi.enfici...@mines-paris.org>
Date: Fri, 11 Sep 2015 16:02:35 +0200
Subject: [PATCH 3/3] CPackDeb: use of libarchive and removal of fakeroot

- using directly libarchive/cmArchiveWrite for creating intermediate tar files
- removing need for fakeroot and managing uname/gname and uid/gid directly from 
libarchive
- managing file permissions directly from libarchive
---
 Modules/CPackDeb.cmake               |   6 -
 Source/CPack/cmCPackDebGenerator.cxx | 274 +++++++++++++++++++++--------------
 2 files changed, 162 insertions(+), 118 deletions(-)

diff --git a/Modules/CPackDeb.cmake b/Modules/CPackDeb.cmake
index 75e9966..502415a 100644
--- a/Modules/CPackDeb.cmake
+++ b/Modules/CPackDeb.cmake
@@ -321,11 +321,6 @@ function(cpack_deb_prepare_package_vars)
     set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF)
   endif()
 
-  find_program(FAKEROOT_EXECUTABLE fakeroot)
-  if(FAKEROOT_EXECUTABLE)
-    set(CPACK_DEBIAN_FAKEROOT_EXECUTABLE ${FAKEROOT_EXECUTABLE})
-  endif()
-
   set(WDIR 
"${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}")
 
   # per component automatic discover: some of the component might not have
@@ -638,7 +633,6 @@ function(cpack_deb_prepare_package_vars)
   set(GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_DEBIAN_PACKAGE_MAINTAINER}" 
PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION 
"${CPACK_DEBIAN_PACKAGE_DESCRIPTION}" PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" 
PARENT_SCOPE)
-  set(GEN_CPACK_DEBIAN_FAKEROOT_EXECUTABLE 
"${CPACK_DEBIAN_FAKEROOT_EXECUTABLE}" PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_COMPRESSION_TYPE "${CPACK_DEBIAN_COMPRESSION_TYPE}" 
PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS "${CPACK_DEBIAN_PACKAGE_RECOMMENDS}" 
PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS "${CPACK_DEBIAN_PACKAGE_SUGGESTS}" 
PARENT_SCOPE)
diff --git a/Source/CPack/cmCPackDebGenerator.cxx 
b/Source/CPack/cmCPackDebGenerator.cxx
index 5049a3f..06c9c4f 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -15,6 +15,7 @@
 #include "cmMakefile.h"
 #include "cmGeneratedFileStream.h"
 #include "cmCPackLog.h"
+#include "cmArchiveWrite.h"
 
 #include <cmsys/SystemTools.hxx>
 #include <cmsys/Glob.hxx>
@@ -388,9 +389,9 @@ int cmCPackDebGenerator::createDeb()
     {
       std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
       dirName += '/';
-        for (std::vector<std::string>::const_iterator fileIt =
-              packageFiles.begin();
-              fileIt != packageFiles.end(); ++ fileIt )
+      for (std::vector<std::string>::const_iterator fileIt =
+           packageFiles.begin();
+           fileIt != packageFiles.end(); ++ fileIt )
         {
         totalSize += cmSystemTools::FileLength(*fileIt);
         }
@@ -401,190 +402,239 @@ int cmCPackDebGenerator::createDeb()
     out << std::endl;
     }
 
-  std::string cmd(this->GetOption("GEN_CPACK_DEBIAN_FAKEROOT_EXECUTABLE"));
+  const std::string strGenWDIR(this->GetOption("GEN_WDIR"));
 
+
+
+  cmArchiveWrite::Compress tar_compression_type = cmArchiveWrite::CompressGZip;
   const char* debian_compression_type =
       this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE");
   if(!debian_compression_type)
-    {
+  {
     debian_compression_type = "gzip";
-    }
+  }
 
-  std::string cmake_tar = " ", compression_modifier = "a", compression_suffix;
+  std::string compression_suffix;
   if(!strcmp(debian_compression_type, "lzma")) {
       compression_suffix = ".lzma";
+      tar_compression_type = cmArchiveWrite::CompressLZMA;
   } else if(!strcmp(debian_compression_type, "xz")) {
       compression_suffix = ".xz";
+      tar_compression_type = cmArchiveWrite::CompressXZ;
   } else if(!strcmp(debian_compression_type, "bzip2")) {
       compression_suffix = ".bz2";
-      compression_modifier = "j";
-      cmake_tar += "\"" + cmSystemTools::GetCMakeCommand() + "\" -E ";
+      tar_compression_type = cmArchiveWrite::CompressBZip2;
   } else if(!strcmp(debian_compression_type, "gzip")) {
       compression_suffix = ".gz";
-      compression_modifier = "z";
-      cmake_tar += "\"" + cmSystemTools::GetCMakeCommand() + "\" -E ";
+      tar_compression_type = cmArchiveWrite::CompressGZip;
   } else if(!strcmp(debian_compression_type, "none")) {
       compression_suffix = "";
-      compression_modifier = "";
-      cmake_tar += "\"" + cmSystemTools::GetCMakeCommand() + "\" -E ";
+      tar_compression_type = cmArchiveWrite::CompressNone;
   } else {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
                     "Error unrecognized compression type: "
                     << debian_compression_type << std::endl);
   }
 
-  cmd += cmake_tar + "tar c" + compression_modifier + "f data.tar"
-      + compression_suffix;
 
-  // now add all directories which have to be compressed
-  // collect all top level install dirs for that
-  // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would give /usr and /opt
-    size_t topLevelLength = std::string(this->GetOption("GEN_WDIR")).length();
-    cmCPackLogger(cmCPackLog::LOG_DEBUG, "WDIR: \""
-          << this->GetOption("GEN_WDIR")
-          << "\", length = " << topLevelLength
+  std::string filename_data_tar = strGenWDIR
+      + "/data.tar" + compression_suffix;
+
+  // atomic file generation for data.tar
+  {
+    cmGeneratedFileStream fileStream_data_tar;
+    fileStream_data_tar.Open(filename_data_tar.c_str(), false, true);
+    if(!fileStream_data_tar)
+    {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+          "Error opening the file \"" << filename_data_tar << "\" for writing"
           << std::endl);
-  std::set<std::string> installDirs;
+      return 0;
+    }
+    cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type, "paxr");
+
+    // uid/gid should be the one of the root user, and this root user has
+    // always uid/gid equal to 0.
+    data_tar.SetUID(0);
+    data_tar.SetGID(0);
+    data_tar.SetUNAME("root");
+    data_tar.SetGNAME("root");
+    data_tar.SetPermissionsMask(~S_IWGRP & ~S_IWOTH);
+
+    // now add all directories which have to be compressed
+    // collect all top level install dirs for that
+    // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would
+    // give /usr and /opt
+    size_t topLevelLength = strGenWDIR.length();
+    cmCPackLogger(cmCPackLog::LOG_DEBUG, "WDIR: \""
+            << strGenWDIR
+            << "\", length = " << topLevelLength
+            << std::endl);
+    std::set<std::string> orderedFiles;
+
+    // we have to reconstruct the parent folders as well
+
+
     for (std::vector<std::string>::const_iterator fileIt =
-        packageFiles.begin();
-        fileIt != packageFiles.end(); ++ fileIt )
+         packageFiles.begin();
+         fileIt != packageFiles.end(); ++ fileIt )
     {
-      cmCPackLogger(cmCPackLog::LOG_DEBUG, "FILEIT: \"" << *fileIt << "\""
-          << std::endl);
-    std::string::size_type slashPos = fileIt->find('/', topLevelLength+1);
-    std::string relativeDir = fileIt->substr(topLevelLength,
-                                             slashPos - topLevelLength);
-      cmCPackLogger(cmCPackLog::LOG_DEBUG, "RELATIVEDIR: \"" << relativeDir
-      << "\"" << std::endl);
-    if (installDirs.find(relativeDir) == installDirs.end())
+      std::string currentPath = *fileIt;
+      while(currentPath != strGenWDIR)
       {
-      installDirs.insert(relativeDir);
-      cmd += " .";
-      cmd += relativeDir;
+        // the last one IS strGenWDIR, but we do not want this one:
+        // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application
+        // should not add XXX/application
+        orderedFiles.insert(currentPath);
+        currentPath = cmSystemTools::CollapseCombinedPath(currentPath, "..");
       }
     }
 
-  std::string output;
-    int retval = -1;
-  int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output,
-      &retval, this->GetOption("GEN_WDIR"), this->GeneratorVerbose, 0);
 
-    if ( !res || retval )
+    for (std::set<std::string>::const_iterator fileIt =
+         orderedFiles.begin();
+         fileIt != orderedFiles.end(); ++ fileIt )
     {
-    std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    tmpFile += "/Deb.log";
-    cmGeneratedFileStream ofs(tmpFile.c_str());
-    ofs << "# Run command: " << cmd << std::endl
-      << "# Working directory: " << toplevel << std::endl
-      << "# Output:" << std::endl
-      << output << std::endl;
-    cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running tar command: "
-      << cmd << std::endl
-      << "Please check " << tmpFile << " for errors" << std::endl);
-    return 0;
+
+      cmCPackLogger(cmCPackLog::LOG_DEBUG, "FILEIT: \"" << *fileIt << "\""
+                    << std::endl);
+      std::string::size_type slashPos = fileIt->find('/', topLevelLength+1);
+      std::string relativeDir = fileIt->substr(topLevelLength,
+                                               slashPos - topLevelLength);
+      cmCPackLogger(cmCPackLog::LOG_DEBUG, "RELATIVEDIR: \"" << relativeDir
+                    << "\"" << std::endl);
+
+      // do not recurse because the loop will do it
+      if(!data_tar.Add(*fileIt, topLevelLength, ".", false))
+      {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+                      "Problem adding file to tar:" << std::endl
+                      << "#top level directory: "
+                      << strGenWDIR << std::endl
+                      << "#file: " << *fileIt << std::endl
+                      << "#error:" << data_tar.GetError() << std::endl);
+        return 0;
+      }
+
     }
+  } // scope for file generation
 
-  std::string md5filename;
-    md5filename = this->GetOption("GEN_WDIR");
-  md5filename += "/md5sums";
 
-    { // the scope is needed for cmGeneratedFileStream
+  std::string md5filename = strGenWDIR + "/md5sums";
+  {
+    // the scope is needed for cmGeneratedFileStream
     cmGeneratedFileStream out(md5filename.c_str());
-    std::vector<std::string>::const_iterator fileIt;
-//       std::string topLevelWithTrailingSlash = toplevel;
+
     std::string topLevelWithTrailingSlash =
         this->GetOption("CPACK_TEMPORARY_DIRECTORY");
     topLevelWithTrailingSlash += '/';
-      for ( fileIt = packageFiles.begin();
-            fileIt != packageFiles.end(); ++ fileIt )
-      {
-      cmd = "\"";
+    for (std::vector<std::string>::const_iterator fileIt =
+           packageFiles.begin();
+         fileIt != packageFiles.end(); ++ fileIt )
+    {
+      std::string cmd = "\"";
       cmd += cmSystemTools::GetCMakeCommand();
       cmd += "\" -E md5sum \"";
       cmd += *fileIt;
       cmd += "\"";
-      //std::string output;
-      //int retVal = -1;
-      res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output,
+
+      std::string output;
+      int retval = -1;
+      int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output,
           &retval, toplevel.c_str(), this->GeneratorVerbose, 0);
       if ( !res || retval )
-        {
+      {
         cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running cmake -E md5sum "
                       << cmd << std::endl);
-        }
+      }
       // debian md5sums entries are like this:
       // 014f3604694729f3bf19263bac599765  usr/bin/ccmake
       // thus strip the full path (with the trailing slash)
       cmSystemTools::ReplaceString(output,
                                    topLevelWithTrailingSlash.c_str(), "");
       out << output;
-      }
+    }
     // each line contains a eol.
     // Do not end the md5sum file with yet another (invalid)
-    }
+  }
 
-    // set md5sum file permissins to RW-R--R-- so that deb lintian doesn't warn
-    // about it
-    cmSystemTools::SetPermissions(md5filename.c_str(),
-        S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 
-    cmd = this->GetOption("GEN_CPACK_DEBIAN_FAKEROOT_EXECUTABLE");
-    cmd += cmake_tar + "tar czf control.tar.gz ./control ./md5sums";
+
+  std::string filename_control_tar = strGenWDIR + "/control.tar.gz";
+  // atomic file generation for control.tar
+  {
+    cmGeneratedFileStream fileStream_control_tar;
+    fileStream_control_tar.Open(filename_control_tar.c_str(), false, true);
+    if(!fileStream_control_tar)
+    {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+          "Error opening the file \"" << filename_control_tar
+          << "\" for writing" << std::endl);
+      return 0;
+    }
+    cmArchiveWrite control_tar(fileStream_control_tar,
+                               tar_compression_type,
+                               "paxr");
+
+    // sets permissions and uid/gid for the files
+    control_tar.SetUID(0);
+    control_tar.SetGID(0);
+    control_tar.SetUNAME("root");
+    control_tar.SetGNAME("root");
+
+    // set md5sum file permissins to RW-R--R-- so that deb lintian
+    // doesn't warn about it
+    control_tar.SetPermissionsMask(~S_IWGRP & ~S_IWOTH);
+
+    // adds control and md5sums
+    if(   !control_tar.Add(md5filename, strGenWDIR.length(), ".")
+       || !control_tar.Add(strGenWDIR + "/control", strGenWDIR.length(), "."))
+    {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+            "Error adding file to tar:" << std::endl
+            << "#top level directory: "
+               << strGenWDIR << std::endl
+            << "#file: \"control\" or \"md5sums\"" << std::endl
+            << "#error:" << control_tar.GetError() << std::endl);
+        return 0;
+    }
+
     const char* controlExtra =
       this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA");
-  if( controlExtra )
+    if( controlExtra )
     {
-    std::vector<std::string> controlExtraList;
-    cmSystemTools::ExpandListArgument(controlExtra, controlExtraList);
-    for(std::vector<std::string>::iterator i =
-          controlExtraList.begin(); i != controlExtraList.end(); ++i)
+      std::vector<std::string> controlExtraList;
+      cmSystemTools::ExpandListArgument(controlExtra, controlExtraList);
+      for(std::vector<std::string>::iterator i = controlExtraList.begin();
+          i != controlExtraList.end(); ++i)
       {
-      std::string filenamename =
-        cmsys::SystemTools::GetFilenameName(*i);
-      std::string localcopy = this->GetOption("GEN_WDIR");
-      localcopy += "/";
-      localcopy += filenamename;
-      // if we can copy the file, it means it does exist, let's add it:
-      if( cmsys::SystemTools::CopyFileIfDifferent(
-            *i, localcopy) )
+        std::string filenamename =
+          cmsys::SystemTools::GetFilenameName(*i);
+        std::string localcopy = strGenWDIR + "/" + filenamename;
+
+        // if we can copy the file, it means it does exist, let's add it:
+        if( cmsys::SystemTools::CopyFileIfDifferent(*i, localcopy) )
         {
-        // debian is picky and need relative to ./ path in the tar.*
-        cmd += " ./";
-        cmd += filenamename;
+          control_tar.Add(localcopy, strGenWDIR.length(), ".");
         }
       }
     }
-  res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output,
-      &retval, this->GetOption("GEN_WDIR"), this->GeneratorVerbose, 0);
+  }
 
-    if ( !res || retval )
-    {
-    std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    tmpFile += "/Deb.log";
-    cmGeneratedFileStream ofs(tmpFile.c_str());
-    ofs << "# Run command: " << cmd << std::endl
-      << "# Working directory: " << toplevel << std::endl
-      << "# Output:" << std::endl
-      << output << std::endl;
-    cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running tar command: "
-      << cmd << std::endl
-      << "Please check " << tmpFile << " for errors" << std::endl);
-    return 0;
-    }
 
   // ar -r your-package-name.deb debian-binary control.tar.* data.tar.*
   // since debian packages require BSD ar (most Linux distros and even
   // FreeBSD and NetBSD ship GNU ar) we use a copy of OpenBSD ar here.
   std::vector<std::string> arFiles;
-    std::string topLevelString = this->GetOption("GEN_WDIR");
+  std::string topLevelString = this->GetOption("GEN_WDIR");
   topLevelString += "/";
   arFiles.push_back(topLevelString + "debian-binary");
   arFiles.push_back(topLevelString + "control.tar.gz");
   arFiles.push_back(topLevelString + "data.tar" + compression_suffix);
-    std::string outputFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    outputFileName += "/";
-    outputFileName += this->GetOption("CPACK_OUTPUT_FILE_NAME");
-    res = ar_append(outputFileName.c_str(), arFiles);
+  std::string outputFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+  outputFileName += "/";
+  outputFileName += this->GetOption("CPACK_OUTPUT_FILE_NAME");
+  int res = ar_append(outputFileName.c_str(), arFiles);
   if ( res!=0 )
     {
     std::string tmpFile = this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
-- 
2.0.1

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to