Directory: | cvmfs/ |
---|---|
File: | cvmfs/manifest.cc |
Date: | 2025-06-22 02:36:02 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 136 | 156 | 87.2% |
Branches: | 154 | 340 | 45.3% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM File System. | ||
3 | */ | ||
4 | |||
5 | #include "manifest.h" | ||
6 | |||
7 | #include <cstdio> | ||
8 | #include <map> | ||
9 | #include <vector> | ||
10 | |||
11 | #include "catalog.h" | ||
12 | #include "util/posix.h" | ||
13 | #include "util/string.h" | ||
14 | |||
15 | using namespace std; // NOLINT | ||
16 | |||
17 | namespace manifest { | ||
18 | |||
19 | 393 | Breadcrumb::Breadcrumb(const std::string &from_string) { | |
20 | 393 | timestamp = 0; | |
21 | 393 | revision = 0; // for backward compatibility: no revision --> revision = 0 | |
22 | |||
23 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 378 times.
|
393 | if (from_string.empty()) { |
24 | 15 | return; | |
25 | } | ||
26 | |||
27 | // Separate hash from timestamp | ||
28 |
1/2✓ Branch 1 taken 378 times.
✗ Branch 2 not taken.
|
378 | std::vector<std::string> vec_split_timestamp = SplitString(from_string, 'T'); |
29 | |||
30 |
1/2✓ Branch 3 taken 378 times.
✗ Branch 4 not taken.
|
378 | catalog_hash = shash::MkFromHexPtr(shash::HexPtr(vec_split_timestamp[0]), |
31 | shash::kSuffixCatalog); | ||
32 | |||
33 |
2/2✓ Branch 1 taken 348 times.
✓ Branch 2 taken 30 times.
|
378 | if (vec_split_timestamp.size() > 1) { |
34 | // check if revision number is included | ||
35 | std::vector<std::string> vec_split_revision = SplitString( | ||
36 |
1/2✓ Branch 2 taken 348 times.
✗ Branch 3 not taken.
|
348 | vec_split_timestamp[1], 'R'); |
37 | |||
38 | // Get local last modified time | ||
39 |
1/2✓ Branch 2 taken 348 times.
✗ Branch 3 not taken.
|
348 | timestamp = String2Uint64(vec_split_revision[0]); |
40 | |||
41 | // Get local revision | ||
42 |
2/2✓ Branch 1 taken 213 times.
✓ Branch 2 taken 135 times.
|
348 | if (vec_split_revision.size() > 1) { |
43 |
1/2✓ Branch 2 taken 213 times.
✗ Branch 3 not taken.
|
213 | revision = String2Uint64(vec_split_revision[1]); |
44 | } | ||
45 | 348 | } | |
46 | 378 | } | |
47 | |||
48 | 392 | bool Breadcrumb::Export(const string &fqrn, const string &directory, | |
49 | const int mode) const { | ||
50 | const string breadcrumb_path = | ||
51 |
3/6✓ Branch 1 taken 392 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 392 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 392 times.
✗ Branch 8 not taken.
|
784 | MakeCanonicalPath(directory) + "/cvmfschecksum." + fqrn; |
52 | 392 | string tmp_path; | |
53 |
1/2✓ Branch 1 taken 392 times.
✗ Branch 2 not taken.
|
392 | FILE *fbreadcrumb = CreateTempFile(breadcrumb_path, mode, "w", &tmp_path); |
54 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | if (fbreadcrumb == NULL) |
55 | ✗ | return false; | |
56 |
1/2✓ Branch 1 taken 392 times.
✗ Branch 2 not taken.
|
392 | string str_breadcrumb = ToString(); |
57 | const int written = | ||
58 |
2/4✓ Branch 2 taken 392 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 392 times.
✗ Branch 6 not taken.
|
392 | fwrite(&(str_breadcrumb[0]), 1, str_breadcrumb.length(), fbreadcrumb); |
59 |
1/2✓ Branch 1 taken 392 times.
✗ Branch 2 not taken.
|
392 | fclose(fbreadcrumb); |
60 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 392 times.
|
392 | if (static_cast<unsigned>(written) != str_breadcrumb.length()) { |
61 | ✗ | unlink(tmp_path.c_str()); | |
62 | ✗ | return false; | |
63 | } | ||
64 | 392 | const int retval = rename(tmp_path.c_str(), breadcrumb_path.c_str()); | |
65 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | if (retval != 0) { |
66 | ✗ | unlink(tmp_path.c_str()); | |
67 | ✗ | return false; | |
68 | } | ||
69 | 392 | return true; | |
70 | 392 | } | |
71 | |||
72 | 976 | std::string Breadcrumb::ToString() const { | |
73 |
2/4✓ Branch 1 taken 976 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 976 times.
✗ Branch 5 not taken.
|
1952 | return catalog_hash.ToString() + "T" |
74 |
3/6✓ Branch 1 taken 976 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 976 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 976 times.
✗ Branch 8 not taken.
|
3904 | + StringifyInt(static_cast<int64_t>(timestamp)) + "R" |
75 |
1/2✓ Branch 2 taken 976 times.
✗ Branch 3 not taken.
|
2928 | + StringifyUint(revision); |
76 | } | ||
77 | |||
78 | |||
79 | //------------------------------------------------------------------------------ | ||
80 | |||
81 | |||
82 | 1128 | Manifest *Manifest::LoadMem(const unsigned char *buffer, | |
83 | const unsigned length) { | ||
84 | 1128 | map<char, string> content; | |
85 |
1/2✓ Branch 1 taken 1128 times.
✗ Branch 2 not taken.
|
1128 | ParseKeyvalMem(buffer, length, &content); |
86 | |||
87 |
1/2✓ Branch 1 taken 1128 times.
✗ Branch 2 not taken.
|
2256 | return Load(content); |
88 | 1128 | } | |
89 | |||
90 | |||
91 | 196 | Manifest *Manifest::LoadFile(const std::string &from_path) { | |
92 | 196 | map<char, string> content; | |
93 |
2/4✓ Branch 1 taken 196 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 196 times.
|
196 | if (!ParseKeyvalPath(from_path, &content)) |
94 | ✗ | return NULL; | |
95 | |||
96 |
1/2✓ Branch 1 taken 196 times.
✗ Branch 2 not taken.
|
196 | return Load(content); |
97 | 196 | } | |
98 | |||
99 | |||
100 | 1324 | Manifest *Manifest::Load(const map<char, string> &content) { | |
101 | 1324 | map<char, string>::const_iterator iter; | |
102 | |||
103 | // Required keys | ||
104 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | shash::Any catalog_hash; |
105 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | shash::Md5 root_path; |
106 | uint32_t ttl; | ||
107 | uint64_t revision; | ||
108 | |||
109 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | iter = content.find('C'); |
110 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1324 times.
|
1324 | if ((iter = content.find('C')) == content.end()) |
111 | ✗ | return NULL; | |
112 |
1/2✓ Branch 3 taken 1324 times.
✗ Branch 4 not taken.
|
1324 | catalog_hash = MkFromHexPtr(shash::HexPtr(iter->second), |
113 | shash::kSuffixCatalog); | ||
114 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1324 times.
|
1324 | if ((iter = content.find('R')) == content.end()) |
115 | ✗ | return NULL; | |
116 |
1/2✓ Branch 3 taken 1324 times.
✗ Branch 4 not taken.
|
1324 | root_path = shash::Md5(shash::HexPtr(iter->second)); |
117 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1324 times.
|
1324 | if ((iter = content.find('D')) == content.end()) |
118 | ✗ | return NULL; | |
119 |
1/2✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
|
1324 | ttl = String2Uint64(iter->second); |
120 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1324 times.
|
1324 | if ((iter = content.find('S')) == content.end()) |
121 | ✗ | return NULL; | |
122 |
1/2✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
|
1324 | revision = String2Uint64(iter->second); |
123 | |||
124 | |||
125 | // Optional keys | ||
126 | 1324 | uint64_t catalog_size = 0; | |
127 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | shash::Any micro_catalog_hash; |
128 | 1324 | string repository_name; | |
129 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | shash::Any certificate; |
130 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | shash::Any history; |
131 | 1324 | uint64_t publish_timestamp = 0; | |
132 | 1324 | bool garbage_collectable = false; | |
133 | 1324 | bool has_alt_catalog_path = false; | |
134 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | shash::Any meta_info; |
135 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
1324 | shash::Any reflog_hash; |
136 | |||
137 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1324 times.
✗ Branch 6 not taken.
|
1324 | if ((iter = content.find('B')) != content.end()) |
138 |
1/2✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
|
1324 | catalog_size = String2Uint64(iter->second); |
139 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1324 times.
|
1324 | if ((iter = content.find('L')) != content.end()) |
140 | ✗ | micro_catalog_hash = MkFromHexPtr(shash::HexPtr(iter->second), | |
141 | shash::kSuffixMicroCatalog); | ||
142 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1324 times.
✗ Branch 6 not taken.
|
1324 | if ((iter = content.find('N')) != content.end()) |
143 |
1/2✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
|
1324 | repository_name = iter->second; |
144 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1324 times.
✗ Branch 6 not taken.
|
1324 | if ((iter = content.find('X')) != content.end()) |
145 |
1/2✓ Branch 3 taken 1324 times.
✗ Branch 4 not taken.
|
1324 | certificate = MkFromHexPtr(shash::HexPtr(iter->second), |
146 | shash::kSuffixCertificate); | ||
147 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1324 times.
✗ Branch 6 not taken.
|
1324 | if ((iter = content.find('H')) != content.end()) |
148 |
1/2✓ Branch 3 taken 1324 times.
✗ Branch 4 not taken.
|
1324 | history = MkFromHexPtr(shash::HexPtr(iter->second), shash::kSuffixHistory); |
149 |
3/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 883 times.
✓ Branch 6 taken 441 times.
|
1324 | if ((iter = content.find('T')) != content.end()) |
150 |
1/2✓ Branch 2 taken 883 times.
✗ Branch 3 not taken.
|
883 | publish_timestamp = String2Uint64(iter->second); |
151 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1324 times.
✗ Branch 6 not taken.
|
1324 | if ((iter = content.find('G')) != content.end()) |
152 | 1324 | garbage_collectable = (iter->second == "yes"); | |
153 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1324 times.
✗ Branch 6 not taken.
|
1324 | if ((iter = content.find('A')) != content.end()) |
154 | 1324 | has_alt_catalog_path = (iter->second == "yes"); | |
155 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1324 times.
|
1324 | if ((iter = content.find('M')) != content.end()) |
156 | ✗ | meta_info = MkFromHexPtr(shash::HexPtr(iter->second), | |
157 | shash::kSuffixMetainfo); | ||
158 |
2/5✓ Branch 2 taken 1324 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1324 times.
|
1324 | if ((iter = content.find('Y')) != content.end()) { |
159 | ✗ | reflog_hash = MkFromHexPtr(shash::HexPtr(iter->second)); | |
160 | } | ||
161 | |||
162 | return new Manifest(catalog_hash, catalog_size, root_path, ttl, revision, | ||
163 | micro_catalog_hash, repository_name, certificate, history, | ||
164 | publish_timestamp, garbage_collectable, | ||
165 |
2/4✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1324 times.
✗ Branch 5 not taken.
|
1324 | has_alt_catalog_path, meta_info, reflog_hash); |
166 | 1324 | } | |
167 | |||
168 | |||
169 | 5377 | Manifest::Manifest(const shash::Any &catalog_hash, | |
170 | const uint64_t catalog_size, | ||
171 | 5377 | const string &root_path) | |
172 | 5377 | : catalog_hash_(catalog_hash) | |
173 | 5377 | , catalog_size_(catalog_size) | |
174 |
1/2✓ Branch 2 taken 5377 times.
✗ Branch 3 not taken.
|
5377 | , root_path_(shash::Md5(shash::AsciiPtr(root_path))) |
175 | 5377 | , ttl_(catalog::Catalog::kDefaultTTL) | |
176 | 5377 | , revision_(0) | |
177 | 5377 | , publish_timestamp_(0) | |
178 | 5377 | , garbage_collectable_(false) | |
179 |
4/8✓ Branch 3 taken 5377 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5377 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5377 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 5377 times.
✗ Branch 13 not taken.
|
5377 | , has_alt_catalog_path_(false) { } |
180 | |||
181 | |||
182 | /** | ||
183 | * Creates the manifest string | ||
184 | */ | ||
185 | 1881 | string Manifest::ExportString() const { | |
186 |
4/8✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1881 times.
✗ Branch 11 not taken.
|
3762 | string manifest = "C" + catalog_hash_.ToString() + "\n" + "B" |
187 |
4/8✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1881 times.
✗ Branch 11 not taken.
|
7524 | + StringifyInt(catalog_size_) + "\n" + "R" |
188 |
6/12✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1881 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1881 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1881 times.
✗ Branch 17 not taken.
|
7524 | + root_path_.ToString() + "\n" + "D" + StringifyInt(ttl_) |
189 |
6/12✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1881 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1881 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1881 times.
✗ Branch 17 not taken.
|
7524 | + "\n" + "S" + StringifyInt(revision_) + "\n" + "G" |
190 |
4/8✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1881 times.
✗ Branch 11 not taken.
|
7524 | + StringifyBool(garbage_collectable_) + "\n" + "A" |
191 |
2/4✓ Branch 2 taken 1881 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1881 times.
✗ Branch 6 not taken.
|
5643 | + StringifyBool(has_alt_catalog_path_) + "\n"; |
192 | |||
193 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1881 times.
|
1881 | if (!micro_catalog_hash_.IsNull()) |
194 | ✗ | manifest += "L" + micro_catalog_hash_.ToString() + "\n"; | |
195 |
1/2✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
|
1881 | if (repository_name_ != "") |
196 |
3/6✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
|
1881 | manifest += "N" + repository_name_ + "\n"; |
197 |
1/2✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
|
1881 | if (!certificate_.IsNull()) |
198 |
4/8✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1881 times.
✗ Branch 11 not taken.
|
1881 | manifest += "X" + certificate_.ToString() + "\n"; |
199 |
1/2✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
|
1881 | if (!history_.IsNull()) |
200 |
4/8✓ Branch 1 taken 1881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1881 times.
✗ Branch 11 not taken.
|
1881 | manifest += "H" + history_.ToString() + "\n"; |
201 |
2/2✓ Branch 0 taken 1251 times.
✓ Branch 1 taken 630 times.
|
1881 | if (publish_timestamp_ > 0) |
202 |
4/8✓ Branch 1 taken 1251 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1251 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1251 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1251 times.
✗ Branch 11 not taken.
|
1251 | manifest += "T" + StringifyInt(publish_timestamp_) + "\n"; |
203 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1881 times.
|
1881 | if (!meta_info_.IsNull()) |
204 | ✗ | manifest += "M" + meta_info_.ToString() + "\n"; | |
205 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1881 times.
|
1881 | if (!reflog_hash_.IsNull()) { |
206 | ✗ | manifest += "Y" + reflog_hash_.ToString() + "\n"; | |
207 | } | ||
208 | // Reserved: Z -> for identification of channel tips | ||
209 | |||
210 | 1881 | return manifest; | |
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Writes the .cvmfspublished file (unsigned). | ||
216 | */ | ||
217 | 98 | bool Manifest::Export(const std::string &path) const { | |
218 |
1/2✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
|
98 | FILE *fmanifest = fopen(path.c_str(), "w"); |
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
|
98 | if (!fmanifest) |
220 | ✗ | return false; | |
221 | |||
222 |
1/2✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
|
98 | string manifest = ExportString(); |
223 | |||
224 |
1/2✓ Branch 3 taken 98 times.
✗ Branch 4 not taken.
|
98 | if (fwrite(manifest.data(), 1, manifest.length(), fmanifest) |
225 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
|
98 | != manifest.length()) { |
226 | ✗ | fclose(fmanifest); | |
227 | ✗ | unlink(path.c_str()); | |
228 | ✗ | return false; | |
229 | } | ||
230 |
1/2✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
|
98 | fclose(fmanifest); |
231 | |||
232 | 98 | return true; | |
233 | 98 | } | |
234 | |||
235 | |||
236 | /** | ||
237 | * Writes the cvmfschecksum.$repository file. Atomic store. | ||
238 | */ | ||
239 | 392 | bool Manifest::ExportBreadcrumb(const string &directory, const int mode) const { | |
240 | 784 | return Breadcrumb(catalog_hash_, publish_timestamp_, revision_) | |
241 |
1/2✓ Branch 1 taken 392 times.
✗ Branch 2 not taken.
|
784 | .Export(repository_name_, directory, mode); |
242 | } | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Read the hash and the last-modified time stamp from the | ||
247 | * cvmfschecksum.$repository file in the given directory. | ||
248 | */ | ||
249 | 1004 | Breadcrumb Manifest::ReadBreadcrumb(const std::string &repo_name, | |
250 | const std::string &directory) { | ||
251 |
1/2✓ Branch 1 taken 1004 times.
✗ Branch 2 not taken.
|
1004 | Breadcrumb breadcrumb; |
252 |
2/4✓ Branch 1 taken 1004 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1004 times.
✗ Branch 5 not taken.
|
1004 | const string breadcrumb_path = directory + "/cvmfschecksum." + repo_name; |
253 |
1/2✓ Branch 2 taken 1004 times.
✗ Branch 3 not taken.
|
1004 | FILE *fbreadcrumb = fopen(breadcrumb_path.c_str(), "r"); |
254 |
2/2✓ Branch 0 taken 746 times.
✓ Branch 1 taken 258 times.
|
1004 | if (!fbreadcrumb) { |
255 | // Return invalid breadcrumb if not found | ||
256 | 746 | return breadcrumb; | |
257 | } | ||
258 | char tmp[164]; | ||
259 |
1/2✓ Branch 1 taken 258 times.
✗ Branch 2 not taken.
|
258 | const size_t read_bytes = fread(tmp, 1, 164, fbreadcrumb); |
260 |
2/2✓ Branch 0 taken 243 times.
✓ Branch 1 taken 15 times.
|
258 | if (read_bytes > 0) { |
261 |
2/4✓ Branch 2 taken 243 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 243 times.
✗ Branch 6 not taken.
|
243 | breadcrumb = Breadcrumb(std::string(tmp, read_bytes)); |
262 | } | ||
263 |
1/2✓ Branch 1 taken 258 times.
✗ Branch 2 not taken.
|
258 | fclose(fbreadcrumb); |
264 | |||
265 | 258 | return breadcrumb; | |
266 | 1004 | } | |
267 | |||
268 | } // namespace manifest | ||
269 |