GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/sync_item_tar.cc
Date: 2025-06-29 02:35:41
Exec Total Coverage
Lines: 45 97 46.4%
Branches: 16 77 20.8%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System
3 */
4
5 #include "sync_item_tar.h"
6
7 #include <string>
8
9 #include "directory_entry.h"
10 #include "duplex_libarchive.h"
11 #include "ingestion/ingestion_source.h"
12 #include "sync_union_tarball.h"
13 #include "util/concurrency.h"
14 #include "util/platform.h"
15
16 namespace publish {
17
18 224 SyncItemTar::SyncItemTar(const std::string &relative_parent_path,
19 const std::string &filename, struct archive *archive,
20 struct archive_entry *entry,
21 Signal *read_archive_signal,
22 const SyncUnion *union_engine, const uid_t uid,
23 224 const gid_t gid)
24 : SyncItem(relative_parent_path, filename, union_engine, kItemUnknown)
25 224 , archive_(archive)
26 224 , archive_entry_(entry)
27 224 , obtained_tar_stat_(false)
28 224 , read_archive_signal_(read_archive_signal)
29 224 , uid_(uid)
30 224 , gid_(gid) {
31
1/2
✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
224 GetStatFromTar();
32 224 }
33
34 SyncItemTar::SyncItemTar(const std::string &relative_parent_path,
35 const std::string &filename, struct archive *archive,
36 struct archive_entry *entry,
37 Signal *read_archive_signal,
38 const SyncUnion *union_engine)
39 : SyncItem(relative_parent_path, filename, union_engine, kItemUnknown)
40 , archive_(archive)
41 , archive_entry_(entry)
42 , obtained_tar_stat_(false)
43 , read_archive_signal_(read_archive_signal)
44 , uid_(-1u)
45 , gid_(-1u) {
46 GetStatFromTar();
47 }
48
49 void SyncItemTar::StatScratch(const bool refresh) const {
50 if (scratch_stat_.obtained && !refresh)
51 return;
52 scratch_stat_.stat = GetStatFromTar();
53 scratch_stat_.error_code = 0;
54 scratch_stat_.obtained = true;
55 }
56
57 224 SyncItemType SyncItemTar::GetScratchFiletype() const {
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 assert(archive_entry_);
59
3/8
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
224 switch (archive_entry_filetype(archive_entry_)) {
60 144 case AE_IFREG: {
61 144 return kItemFile;
62 break;
63 }
64 16 case AE_IFLNK: {
65 16 return kItemSymlink;
66 break;
67 }
68 case AE_IFSOCK: {
69 return kItemSocket;
70 break;
71 }
72 case AE_IFCHR: {
73 return kItemCharacterDevice;
74 break;
75 }
76 case AE_IFBLK: {
77 return kItemBlockDevice;
78 break;
79 }
80 64 case AE_IFDIR: {
81 64 return kItemDir;
82 break;
83 }
84 case AE_IFIFO: {
85 return kItemFifo;
86 break;
87 }
88 default:
89 return kItemUnknown;
90 break;
91 }
92 }
93
94 784 bool SyncItemTar::IsType(const SyncItemType expected_type) const {
95
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 560 times.
784 if (scratch_type_ == kItemUnknown) {
96 224 scratch_type_ = GetScratchFiletype();
97 }
98 784 return scratch_type_ == expected_type;
99 }
100
101 224 platform_stat64 SyncItemTar::GetStatFromTar() const {
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 assert(archive_entry_);
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 if (obtained_tar_stat_)
104 return tar_stat_;
105
106 224 const struct stat *entry_stat = archive_entry_stat(archive_entry_);
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 assert(NULL != entry_stat);
108
109 224 tar_stat_.st_mode = entry_stat->st_mode;
110
111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 if (uid_ != -1u) {
112 tar_stat_.st_uid = uid_;
113 } else {
114 224 tar_stat_.st_uid = entry_stat->st_uid;
115 }
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 if (gid_ != -1u) {
117 tar_stat_.st_gid = gid_;
118 } else {
119 224 tar_stat_.st_gid = entry_stat->st_gid;
120 }
121
122 224 tar_stat_.st_rdev = entry_stat->st_rdev;
123 224 tar_stat_.st_size = entry_stat->st_size;
124 224 tar_stat_.st_mtime = entry_stat->st_mtime;
125 #ifdef __APPLE__
126 tar_stat_.st_mtimespec.tv_nsec = entry_stat->st_mtimespec.tv_nsec;
127 #else
128 224 tar_stat_.st_mtim.tv_nsec = entry_stat->st_mtim.tv_nsec;
129 #endif
130 224 tar_stat_.st_nlink = entry_stat->st_nlink;
131
132
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 160 times.
224 if (IsDirectory()) {
133 64 tar_stat_.st_size = 4096;
134 }
135
136 224 obtained_tar_stat_ = true;
137
138 224 return tar_stat_;
139 }
140
141 catalog::DirectoryEntryBase SyncItemTar::CreateBasicCatalogDirent(
142 bool enable_mtime_ns) const {
143 assert(obtained_tar_stat_);
144
145 catalog::DirectoryEntryBase dirent;
146
147 // inode and parent inode is determined at runtime of client
148 dirent.inode_ = catalog::DirectoryEntry::kInvalidInode;
149
150 // tarfiles do not keep information about the linkcount, so it should always
151 // appear as zero
152 assert(this->tar_stat_.st_nlink == 0);
153 dirent.linkcount_ = 1;
154
155 dirent.mode_ = this->tar_stat_.st_mode;
156 dirent.uid_ = this->tar_stat_.st_uid;
157 dirent.gid_ = this->tar_stat_.st_gid;
158 dirent.size_ = this->tar_stat_.st_size;
159 dirent.mtime_ = this->tar_stat_.st_mtime;
160 dirent.checksum_ = this->GetContentHash();
161 dirent.is_external_file_ = this->IsExternalData();
162 dirent.compression_algorithm_ = this->GetCompressionAlgorithm();
163
164 dirent.name_.Assign(this->filename().data(), this->filename().length());
165
166 if (this->IsSymlink()) {
167 const std::string symlink(archive_entry_symlink(archive_entry_));
168 dirent.symlink_.Assign(symlink.c_str(), symlink.length());
169 }
170
171 if (this->IsCharacterDevice() || this->IsBlockDevice()) {
172 dirent.size_ = makedev(major(tar_stat_.st_rdev), minor(tar_stat_.st_rdev));
173 }
174
175 if (enable_mtime_ns) {
176 #ifdef __APPLE__
177 dirent.mtime_ns_ = static_cast<int32_t>(
178 this->tar_stat_.st_mtimespec.tv_nsec);
179 #else
180 dirent.mtime_ns_ = static_cast<int32_t>(this->tar_stat_.st_mtim.tv_nsec);
181 #endif
182 }
183
184 assert(dirent.IsRegular() || dirent.IsDirectory() || dirent.IsLink()
185 || dirent.IsSpecial());
186
187 return dirent;
188 }
189
190 144 IngestionSource *SyncItemTar::CreateIngestionSource() const {
191 288 return new TarIngestionSource(GetUnionPath(), archive_, archive_entry_,
192
2/4
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
288 read_archive_signal_);
193 }
194 } // namespace publish
195