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