/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once #include "cmConfigure.h" // IWYU pragma: keep #include #include #include #if defined(CMAKE_BOOTSTRAP) # 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 this->Value; } private: T Value; bool IsValueSet; }; /** \class cmArchiveWrite * \brief Wrapper around libarchive for writing. * */ class cmArchiveWrite { public: /** Compression type. */ enum Compress { CompressNone, CompressCompress, CompressGZip, CompressBZip2, CompressLZMA, CompressXZ, CompressZstd }; /** Construct with output stream to which to write archive. */ cmArchiveWrite(std::ostream& os, Compress c = CompressNone, std::string const& format = "paxr", int compressionLevel = 0, int numThreads = 1); ~cmArchiveWrite(); cmArchiveWrite(const cmArchiveWrite&) = delete; cmArchiveWrite& operator=(const cmArchiveWrite&) = delete; bool Open(); /** * Add a path (file or directory) to the archive. Directories are * added recursively. The "path" must be readable on disk, either * full path or relative to current working directory. The "skip" * value indicates how many leading bytes from the input path to * 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 = nullptr, bool recursive = true); /** Returns true if there has been no error. */ explicit operator bool() const { return this->Okay(); } /** Returns true if there has been an error. */ bool operator!() const { return !this->Okay(); } /** Return the error string; empty if none. */ std::string GetError() const { return this->Error; } // TODO: More general callback instead of hard-coding calls to // std::cout. 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(int 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(int 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 recursive = true); bool AddFile(const char* file, size_t skip, const char* prefix); bool AddData(const char* file, size_t size); struct Callback; friend struct Callback; class Entry; std::ostream& Stream; struct archive* Archive; struct archive* Disk; bool Verbose = false; 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; };