GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/path_filters/dirtab.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 88 96 91.7%
Branches: 68 92 73.9%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "dirtab.h"
6
7 #include <cassert>
8 #include <cerrno>
9 #include <cstdio>
10 #include <cstdlib>
11
12 #include "util/logging.h"
13 #include "util/posix.h"
14 #include "util/string.h"
15
16 namespace catalog {
17
18 24 Dirtab::Dirtab() : valid_(true) {}
19
20
21 1 bool Dirtab::Open(const std::string &dirtab_path) {
22
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!FileExists(dirtab_path)) {
23 LogCvmfs(kLogCatalog, kLogStderr, "Cannot find dirtab at '%s'",
24 dirtab_path.c_str());
25 valid_ = false;
26 return valid_;
27 }
28
29 1 FILE *dirtab_file = fopen(dirtab_path.c_str(), "r");
30
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dirtab_file == NULL) {
31 LogCvmfs(kLogCatalog, kLogStderr, "Cannot open dirtab for reading at '%s' "
32 "(errno: %d)",
33 dirtab_path.c_str(), errno);
34 valid_ = false;
35 return valid_;
36 }
37
38 1 valid_ = Parse(dirtab_file);
39 1 fclose(dirtab_file);
40 1 return valid_;
41 }
42
43 20 bool Dirtab::Parse(const std::string &dirtab) {
44 20 valid_ = true;
45 20 off_t line_offset = 0;
46
2/2
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 20 times.
114 while (line_offset < static_cast<off_t>(dirtab.size())) {
47 188 std::string line = GetLineMem(dirtab.c_str() + line_offset,
48
1/2
✓ Branch 3 taken 94 times.
✗ Branch 4 not taken.
94 dirtab.size() - line_offset);
49 94 line_offset += line.size() + 1; // +1 == skipped \n
50
3/4
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 92 times.
94 if (!ParseLine(line)) {
51 2 valid_ = false;
52 }
53 94 }
54
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 1 times.
20 valid_ = valid_ && CheckRuleValidity();
55 20 return valid_;
56 }
57
58
59 2 bool Dirtab::Parse(FILE *dirtab_file) {
60 2 valid_ = true;
61 2 std::string line;
62
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
4 while (GetLineFile(dirtab_file, &line)) {
63
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (!ParseLine(line)) {
64 valid_ = false;
65 }
66 }
67
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 valid_ = valid_ && CheckRuleValidity();
68 2 return valid_;
69 2 }
70
71
72 96 bool Dirtab::ParseLine(const std::string &line) {
73 // line parsing is done using std::string iterators. Each parsing method ex-
74 // pects an iterator and the end iterator. While parsing itr is constantly
75 // incremented to walk through the given .cvmfsdirtab line.
76 96 std::string::const_iterator itr = line.begin();
77 96 const std::string::const_iterator iend = line.end();
78 96 bool negation = false;
79
80 // parse preamble
81 96 SkipWhitespace(iend, &itr);
82
2/2
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 67 times.
96 if (*itr == Dirtab::kCommentMarker) {
83 29 return true;
84
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 39 times.
67 } else if (*itr == Dirtab::kNegationMarker) {
85 28 negation = true;
86 28 ++itr;
87 28 SkipWhitespace(iend, &itr);
88 }
89
90 // extract and parse pathspec
91
2/4
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 67 times.
✗ Branch 6 not taken.
134 std::string pathspec_str(Trim(std::string(itr, iend)));
92
1/2
✓ Branch 1 taken 67 times.
✗ Branch 2 not taken.
67 return this->ParsePathspec(pathspec_str, negation);
93 67 }
94
95 77 bool Dirtab::ParsePathspec(const std::string &pathspec_str, bool negation) {
96
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 67 times.
77 if (pathspec_str.empty()) {
97 10 return true;
98 }
99
1/2
✓ Branch 1 taken 67 times.
✗ Branch 2 not taken.
67 Pathspec pathspec(pathspec_str);
100
101 // all generated Pathspecs need to be valid and positive rules must be
102 // absolute. Otherwise the .cvmfsdirtab is not valid.
103
4/4
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 65 times.
133 if ( !pathspec.IsValid() ||
104
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 27 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 38 times.
66 (!negation && !pathspec.IsAbsolute())) {
105 2 return false;
106 }
107
108 // create a new dirtab rule
109
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 const Rule rule(pathspec, negation);
110
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 AddRule(rule);
111 65 return true;
112 67 }
113
114
115 65 void Dirtab::AddRule(const Rule &rule) {
116
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 38 times.
65 if (rule.is_negation) {
117 27 negative_rules_.push_back(rule);
118 } else {
119 38 positive_rules_.push_back(rule);
120 }
121 65 }
122
123
124 20 bool Dirtab::CheckRuleValidity() const {
125 // check if there are contradicting positive and negative rules
126 20 Rules::const_iterator p = positive_rules_.begin();
127 20 const Rules::const_iterator pend = positive_rules_.end();
128
2/2
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 19 times.
56 for (; p != pend; ++p) {
129
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
37 assert(!p->is_negation);
130 37 Rules::const_iterator n = negative_rules_.begin();
131 37 const Rules::const_iterator nend = negative_rules_.end();
132
2/2
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 36 times.
91 for (; n != nend; ++n) {
133
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
55 assert(n->is_negation);
134
3/4
✓ Branch 3 taken 55 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 54 times.
55 if (p->pathspec == n->pathspec) {
135 1 return false;
136 }
137 }
138 }
139
140 19 return true;
141 }
142
143
144 83 bool Dirtab::IsMatching(const std::string &path) const {
145 // check if path has a positive match
146 83 bool has_positive_match = false;
147 83 Rules::const_iterator p = positive_rules_.begin();
148 83 const Rules::const_iterator pend = positive_rules_.end();
149
2/2
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 40 times.
214 for (; p != pend; ++p) {
150
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
174 assert(!p->is_negation);
151
3/4
✓ Branch 2 taken 174 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 131 times.
174 if (p->pathspec.IsMatching(path)) {
152 43 has_positive_match = true;
153 43 break;
154 }
155 }
156
157
5/6
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 40 times.
✓ Branch 3 taken 43 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 36 times.
✓ Branch 6 taken 7 times.
83 return has_positive_match && !IsOpposing(path);
158 }
159
160
161 159 bool Dirtab::IsOpposing(const std::string &path) const {
162 159 Rules::const_iterator n = negative_rules_.begin();
163 159 const Rules::const_iterator nend = negative_rules_.end();
164
2/2
✓ Branch 2 taken 264 times.
✓ Branch 3 taken 131 times.
395 for (; n != nend; ++n) {
165
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 264 times.
264 assert(n->is_negation);
166
3/4
✓ Branch 2 taken 264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 236 times.
264 if (n->pathspec.IsMatchingRelaxed(path)) {
167 28 return true;
168 }
169 }
170
171 131 return false;
172 }
173
174 } // namespace catalog
175