Coverage Report

Created: 2026-04-29 07:01

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