From 415405a308239f2904c9e2d30e4a3d699ccf01a0 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Fri, 11 Sep 2015 20:00:50 +0200 Subject: [PATCH] cmArchiveWrite: control user/group, permissions and recursive file adding --- Source/cmArchiveWrite.cxx | 39 ++++++++++++++-- Source/cmArchiveWrite.h | 95 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 6 deletions(-) diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 9f5632466..79469509c 100644 --- a/Source/cmArchiveWrite.cxx +++ b/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); diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index e6f515ddc..8dbbb8372 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -18,6 +18,22 @@ # error "cmArchiveWrite not allowed during bootstrap build!" #endif +template +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 Uid; + + //! GUID of the user in the tar file + cmArchiveWriteOptional Gid; + + //! UNAME/GNAME of the user (does not override UID/GID) + //!@{ + std::string Uname; + std::string Gname; + //!@} + + //! Permissions on files/folders + cmArchiveWriteOptional Permissions; + cmArchiveWriteOptional PermissionsMask; }; #endif