Kaynağa Gözat

cmArchiveWrite: control user/group, permissions and recursive file adding

Raffi Enficiaud 10 yıl önce
ebeveyn
işleme
415405a308
2 değiştirilmiş dosya ile 128 ekleme ve 6 silme
  1. 35 4
      Source/cmArchiveWrite.cxx
  2. 93 2
      Source/cmArchiveWrite.h

+ 35 - 4
Source/cmArchiveWrite.cxx

@@ -181,7 +181,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 +192,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 +282,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.IsSet() && this->Gid.IsSet())
+    {
+    archive_entry_set_uid(e, this->Uid.Get());
+    archive_entry_set_gid(e, this->Gid.Get());
+    }
+
+  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.IsSet())
+    {
+    archive_entry_set_perm(e, this->Permissions.Get());
+    }
+
+  if (this->PermissionsMask.IsSet())
+    {
+    mode_t perm = archive_entry_perm(e);
+    archive_entry_set_perm(e, perm & this->PermissionsMask.Get());
+    }
+
   // Clear acl and xattr fields not useful for distribution.
   archive_entry_acl_clear(e);
   archive_entry_xattr_clear(e);

+ 93 - 2
Source/cmArchiveWrite.h

@@ -18,6 +18,22 @@
 # error "cmArchiveWrite not allowed during bootstrap build!"
 #endif
 
+template<typename T>
+class cmArchiveWriteOptional
+{
+public:
+  cmArchiveWriteOptional() {this->Clear();}
+  explicit cmArchiveWriteOptional(T val) {this->Set(val);}
+
+  void Set(T val) {this->IsValueSet = true; this->Value=val;}
+  void Clear() {this->IsValueSet = false;}
+  bool IsSet() const {return this->IsValueSet;}
+  T Get() const {return Value;}
+private:
+  T Value;
+  bool IsValueSet;
+};
+
 /** \class cmArchiveWrite
  * \brief Wrapper around libarchive for writing.
  *
@@ -52,7 +68,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 +88,65 @@ 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
+  void SetPermissions(mode_t permissions_)
+    {
+    this->Permissions.Set(permissions_);
+    }
+
+  //! Clears permissions - default is used instead
+  void ClearPermissions() { this->Permissions.Clear(); }
+
+  //! Sets the permissions mask of files/folders
+  //!
+  //! The permissions will be copied from the existing file
+  //! or folder. The mask will then be applied to unset
+  //! some of them
+  void SetPermissionsMask(mode_t permissionsMask_)
+    {
+    this->PermissionsMask.Set(permissionsMask_);
+    }
+
+  //! Clears permissions mask - default is used instead
+  void ClearPermissionsMask()
+    {
+    this->PermissionsMask.Clear();
+    }
+
+  //! Sets UID and GID to be used in the tar file
+  void SetUIDAndGID(int uid_, int gid_)
+    {
+    this->Uid.Set(uid_);
+    this->Gid.Set(gid_);
+    }
+
+  //! Clears UID and GID to be used in the tar file - default is used instead
+  void ClearUIDAndGID()
+    {
+    this->Uid.Clear();
+    this->Gid.Clear();
+    }
+
+  //! Sets UNAME and GNAME to be used in the tar file
+  void SetUNAMEAndGNAME(const std::string& uname_, const std::string& gname_)
+    {
+    this->Uname = uname_;
+    this->Gname = gname_;
+    }
+
+  //! Clears UNAME and GNAME to be used in the tar file
+  //! default is used instead
+  void ClearUNAMEAndGNAME()
+    {
+    this->Uname = "";
+    this->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 +162,22 @@ private:
   std::string Format;
   std::string Error;
   std::string MTime;
+
+  //! UID of the user in the tar file
+  cmArchiveWriteOptional<int> Uid;
+
+  //! GUID of the user in the tar file
+  cmArchiveWriteOptional<int> Gid;
+
+  //! UNAME/GNAME of the user (does not override UID/GID)
+  //!@{
+  std::string Uname;
+  std::string Gname;
+  //!@}
+
+  //! Permissions on files/folders
+  cmArchiveWriteOptional<mode_t> Permissions;
+  cmArchiveWriteOptional<mode_t> PermissionsMask;
 };
 
 #endif