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 |