Coverage Report

Created: 2026-02-09 06:05

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", int compressionLevel = 0,
59
                 int numThreads = 1);
60
61
  ~cmArchiveWrite();
62
63
  cmArchiveWrite(cmArchiveWrite const&) = delete;
64
  cmArchiveWrite& operator=(cmArchiveWrite const&) = delete;
65
66
  bool Open();
67
68
  /**
69
   * Add a path (file or directory) to the archive.  Directories are
70
   * added recursively.  The "path" must be readable on disk, either
71
   * full path or relative to current working directory.  The "skip"
72
   * value indicates how many leading bytes from the input path to
73
   * skip.  The remaining part of the input path is appended to the
74
   * "prefix" value to construct the final name in the archive.
75
   */
76
  bool Add(std::string path, size_t skip = 0, char const* prefix = nullptr,
77
           bool recursive = true);
78
79
  /** Returns true if there has been no error.  */
80
0
  explicit operator bool() const { return this->Okay(); }
81
82
  /** Returns true if there has been an error.  */
83
0
  bool operator!() const { return !this->Okay(); }
84
85
  /** Return the error string; empty if none.  */
86
0
  std::string GetError() const { return this->Error; }
87
88
  // TODO: More general callback instead of hard-coding calls to
89
  // std::cout.
90
0
  void SetVerbose(bool v) { this->Verbose = v; }
91
92
0
  void SetMTime(std::string const& t) { this->MTime = t; }
93
94
  //! Sets the permissions of the added files/folders
95
  void SetPermissions(int permissions_)
96
0
  {
97
0
    this->Permissions.Set(permissions_);
98
0
  }
99
100
  //! Clears permissions - default is used instead
101
0
  void ClearPermissions() { this->Permissions.Clear(); }
102
103
  //! Sets the permissions mask of files/folders
104
  //!
105
  //! The permissions will be copied from the existing file
106
  //! or folder. The mask will then be applied to unset
107
  //! some of them
108
  void SetPermissionsMask(int permissionsMask_)
109
0
  {
110
0
    this->PermissionsMask.Set(permissionsMask_);
111
0
  }
112
113
  //! Clears permissions mask - default is used instead
114
0
  void ClearPermissionsMask() { this->PermissionsMask.Clear(); }
115
116
  //! Sets UID and GID to be used in the tar file
117
  void SetUIDAndGID(int uid_, int gid_)
118
0
  {
119
0
    this->Uid.Set(uid_);
120
0
    this->Gid.Set(gid_);
121
0
  }
122
123
  //! Clears UID and GID to be used in the tar file - default is used instead
124
  void ClearUIDAndGID()
125
0
  {
126
0
    this->Uid.Clear();
127
0
    this->Gid.Clear();
128
0
  }
129
130
  //! Sets UNAME and GNAME to be used in the tar file
131
  void SetUNAMEAndGNAME(std::string const& uname_, std::string const& gname_)
132
0
  {
133
0
    this->Uname = uname_;
134
0
    this->Gname = gname_;
135
0
  }
136
137
  //! Clears UNAME and GNAME to be used in the tar file
138
  //! default is used instead
139
  void ClearUNAMEAndGNAME()
140
0
  {
141
0
    this->Uname = "";
142
0
    this->Gname = "";
143
0
  }
144
145
private:
146
0
  bool Okay() const { return this->Error.empty(); }
147
  bool AddPath(char const* path, size_t skip, char const* prefix,
148
               bool recursive = true);
149
  bool AddFile(char const* file, size_t skip, char const* prefix);
150
  bool AddData(char const* file, size_t size);
151
152
  struct Callback;
153
  friend struct Callback;
154
155
  class Entry;
156
157
  std::ostream& Stream;
158
  struct archive* Archive;
159
  struct archive* Disk;
160
  bool Verbose = false;
161
  std::string Format;
162
  std::string Error;
163
  std::string MTime;
164
165
  //! UID of the user in the tar file
166
  cmArchiveWriteOptional<int> Uid;
167
168
  //! GUID of the user in the tar file
169
  cmArchiveWriteOptional<int> Gid;
170
171
  //! UNAME/GNAME of the user (does not override UID/GID)
172
  //!@{
173
  std::string Uname;
174
  std::string Gname;
175
  //!@}
176
177
  //! Permissions on files/folders
178
  cmArchiveWriteOptional<int> Permissions;
179
  cmArchiveWriteOptional<int> PermissionsMask;
180
};