Coverage Report

Created: 2026-07-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmArchiveWrite.h
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#pragma once
4
5
#include "cmConfigure.h" // IWYU pragma: keep
6
7
#include <cstddef>
8
#include <iosfwd>
9
#include <string>
10
#include <vector>
11
12
#if defined(CMAKE_BOOTSTRAP)
13
#  error "cmArchiveWrite not allowed during bootstrap build!"
14
#endif
15
16
template <typename T>
17
class cmArchiveWriteOptional
18
{
19
public:
20
0
  cmArchiveWriteOptional() { this->Clear(); }
21
  explicit cmArchiveWriteOptional(T val) { this->Set(val); }
22
23
  void Set(T val)
24
0
  {
25
0
    this->IsValueSet = true;
26
0
    this->Value = val;
27
0
  }
28
0
  void Clear() { this->IsValueSet = false; }
29
0
  bool IsSet() const { return this->IsValueSet; }
30
0
  T Get() const { return this->Value; }
31
32
private:
33
  T Value;
34
  bool IsValueSet;
35
};
36
37
/** \class cmArchiveWrite
38
 * \brief Wrapper around libarchive for writing.
39
 *
40
 */
41
class cmArchiveWrite
42
{
43
public:
44
  /** Compression type.  */
45
  enum Compress
46
  {
47
    CompressNone,
48
    CompressCompress,
49
    CompressGZip,
50
    CompressBZip2,
51
    CompressLZMA,
52
    CompressXZ,
53
    CompressZstd,
54
    CompressPPMd,
55
  };
56
57
  /** Construct with output stream to which to write archive.  */
58
  cmArchiveWrite(std::ostream& os, Compress c = CompressNone,
59
                 std::string const& format = "paxr",
60
                 std::string const& encoding = "UTF-8",
61
                 int compressionLevel = 0, int numThreads = 1);
62
63
  ~cmArchiveWrite();
64
65
  cmArchiveWrite(cmArchiveWrite const&) = delete;
66
  cmArchiveWrite& operator=(cmArchiveWrite const&) = delete;
67
68
  bool Open();
69
70
  /**
71
   * Add a path (file or directory) to the archive.  Directories are
72
   * added recursively.  The "path" must be readable on disk, either
73
   * full path or relative to current working directory.  The "skip"
74
   * value indicates how many leading bytes from the input path to
75
   * skip.  The remaining part of the input path is appended to the
76
   * "prefix" value to construct the final name in the archive.
77
   */
78
  bool Add(std::string path, size_t skip = 0, char const* prefix = nullptr,
79
           bool recursive = true);
80
81
  /** Returns true if there has been no error.  */
82
0
  explicit operator bool() const { return this->Okay(); }
83
84
  /** Returns true if there has been an error.  */
85
0
  bool operator!() const { return !this->Okay(); }
86
87
  /** Return the error string; empty if none.  */
88
0
  std::string GetError() const { return this->Error; }
89
90
  // TODO: More general callback instead of hard-coding calls to
91
  // std::cout.
92
0
  void SetVerbose(bool v) { this->Verbose = v; }
93
94
0
  void SetMTime(std::string const& t) { this->MTime = t; }
95
96
  //! Sets the permissions of the added files/folders
97
  void SetPermissions(int permissions_)
98
0
  {
99
0
    this->Permissions.Set(permissions_);
100
0
  }
101
102
  //! Clears permissions - default is used instead
103
0
  void ClearPermissions() { this->Permissions.Clear(); }
104
105
  //! Sets the permissions mask of files/folders
106
  //!
107
  //! The permissions will be copied from the existing file
108
  //! or folder. The mask will then be applied to unset
109
  //! some of them
110
  void SetPermissionsMask(int permissionsMask_)
111
0
  {
112
0
    this->PermissionsMask.Set(permissionsMask_);
113
0
  }
114
115
  //! Clears permissions mask - default is used instead
116
0
  void ClearPermissionsMask() { this->PermissionsMask.Clear(); }
117
118
  //! Sets UID and GID to be used in the tar file
119
  void SetUIDAndGID(int uid_, int gid_)
120
0
  {
121
0
    this->Uid.Set(uid_);
122
0
    this->Gid.Set(gid_);
123
0
  }
124
125
  //! Clears UID and GID to be used in the tar file - default is used instead
126
  void ClearUIDAndGID()
127
0
  {
128
0
    this->Uid.Clear();
129
0
    this->Gid.Clear();
130
0
  }
131
132
  //! Sets UNAME and GNAME to be used in the tar file
133
  void SetUNAMEAndGNAME(std::string const& uname_, std::string const& gname_)
134
0
  {
135
0
    this->Uname = uname_;
136
0
    this->Gname = gname_;
137
0
  }
138
139
  //! Clears UNAME and GNAME to be used in the tar file
140
  //! default is used instead
141
  void ClearUNAMEAndGNAME()
142
0
  {
143
0
    this->Uname = "";
144
0
    this->Gname = "";
145
0
  }
146
147
  //! Sets exclusion patterns.  Any path whose archive entry name matches one
148
  //! of the patterns is skipped, and excluded directories are not descended
149
  //! into.  Returns false and sets the error if a pattern cannot be added.
150
  bool SetExcludePatterns(std::vector<std::string> const& patterns);
151
152
private:
153
0
  bool Okay() const { return this->Error.empty(); }
154
  bool AddPath(std::string const& path, size_t skip, char const* prefix,
155
               bool recursive = true);
156
  bool AddFile(std::string const& file, size_t skip, char const* prefix);
157
  bool AddData(std::string const& file, size_t size);
158
159
  struct Callback;
160
  friend struct Callback;
161
162
  class Entry;
163
164
  std::ostream& Stream;
165
  struct archive* Archive;
166
  struct archive* Disk;
167
  struct archive* MatchObject = nullptr;
168
  bool Verbose = false;
169
  std::string Format;
170
  std::string Error;
171
  std::string MTime;
172
173
  //! UID of the user in the tar file
174
  cmArchiveWriteOptional<int> Uid;
175
176
  //! GUID of the user in the tar file
177
  cmArchiveWriteOptional<int> Gid;
178
179
  //! UNAME/GNAME of the user (does not override UID/GID)
180
  //!@{
181
  std::string Uname;
182
  std::string Gname;
183
  //!@}
184
185
  //! Permissions on files/folders
186
  cmArchiveWriteOptional<int> Permissions;
187
  cmArchiveWriteOptional<int> PermissionsMask;
188
};