cmArchiveWrite.h 4.61 KB
Newer Older
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3 4 5
#ifndef cmArchiveWrite_h
#define cmArchiveWrite_h

6
#include "cmConfigure.h" // IWYU pragma: keep
7 8 9 10

#include <iosfwd>
#include <stddef.h>
#include <string>
11 12

#if !defined(CMAKE_BUILD_WITH_CMAKE)
13
#  error "cmArchiveWrite not allowed during bootstrap build!"
14 15
#endif

16
template <typename T>
17 18 19
class cmArchiveWriteOptional
{
public:
20 21
  cmArchiveWriteOptional() { this->Clear(); }
  explicit cmArchiveWriteOptional(T val) { this->Set(val); }
22

23 24 25 26 27 28 29 30
  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; }
31

32 33 34 35 36
private:
  T Value;
  bool IsValueSet;
};

37 38 39 40 41 42 43 44 45 46 47
/** \class cmArchiveWrite
 * \brief Wrapper around libarchive for writing.
 *
 */
class cmArchiveWrite
{
public:
  /** Compression type.  */
  enum Compress
  {
    CompressNone,
48
    CompressCompress,
49
    CompressGZip,
50
    CompressBZip2,
51
    CompressLZMA,
52 53
    CompressXZ,
    CompressZstd
54 55
  };

56
  /** Construct with output stream to which to write archive.  */
57
  cmArchiveWrite(std::ostream& os, Compress c = CompressNone,
58
                 std::string const& format = "paxr");
59

60 61
  ~cmArchiveWrite();

62 63 64
  cmArchiveWrite(const cmArchiveWrite&) = delete;
  cmArchiveWrite& operator=(const cmArchiveWrite&) = delete;

65 66 67 68 69 70 71 72
  /**
   * 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.
   */
Daniel Pfeifer's avatar
Daniel Pfeifer committed
73
  bool Add(std::string path, size_t skip = 0, const char* prefix = nullptr,
74
           bool recursive = true);
75 76

  /** Returns true if there has been no error.  */
wahikihiki's avatar
wahikihiki committed
77
  explicit operator bool() const { return this->Okay(); }
78 79 80 81 82 83 84 85 86 87 88

  /** 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; }

89
  void SetMTime(std::string const& t) { this->MTime = t; }
90 91

  //! Sets the permissions of the added files/folders
92
  void SetPermissions(int permissions_)
93
  {
94
    this->Permissions.Set(permissions_);
95
  }
96 97 98 99 100 101 102 103 104

  //! 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
105
  void SetPermissionsMask(int permissionsMask_)
106
  {
107
    this->PermissionsMask.Set(permissionsMask_);
108
  }
109 110

  //! Clears permissions mask - default is used instead
111
  void ClearPermissionsMask() { this->PermissionsMask.Clear(); }
112 113 114

  //! Sets UID and GID to be used in the tar file
  void SetUIDAndGID(int uid_, int gid_)
115
  {
116 117
    this->Uid.Set(uid_);
    this->Gid.Set(gid_);
118
  }
119 120 121

  //! Clears UID and GID to be used in the tar file - default is used instead
  void ClearUIDAndGID()
122
  {
123 124
    this->Uid.Clear();
    this->Gid.Clear();
125
  }
126 127 128

  //! Sets UNAME and GNAME to be used in the tar file
  void SetUNAMEAndGNAME(const std::string& uname_, const std::string& gname_)
129
  {
130 131
    this->Uname = uname_;
    this->Gname = gname_;
132
  }
133 134 135 136

  //! Clears UNAME and GNAME to be used in the tar file
  //! default is used instead
  void ClearUNAMEAndGNAME()
137
  {
138 139
    this->Uname = "";
    this->Gname = "";
140
  }
141

142 143
private:
  bool Okay() const { return this->Error.empty(); }
144 145
  bool AddPath(const char* path, size_t skip, const char* prefix,
               bool recursive = true);
146 147 148 149 150 151 152 153 154 155 156 157
  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;
158
  std::string Format;
159
  std::string Error;
160
  std::string MTime;
161 162 163 164 165 166 167 168 169 170 171 172 173 174

  //! 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
175 176
  cmArchiveWriteOptional<int> Permissions;
  cmArchiveWriteOptional<int> PermissionsMask;
177 178 179
};

#endif