CernVM-FS  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dirtab.cc
Go to the documentation of this file.
1 
5 #include "dirtab.h"
6 
7 #include <cassert>
8 #include <cerrno>
9 #include <cstdio>
10 #include <cstdlib>
11 
12 #include "logging.h"
13 #include "util/posix.h"
14 #include "util/string.h"
15 
16 namespace catalog {
17 
18 Dirtab::Dirtab() : valid_(true) {}
19 
20 
21 bool Dirtab::Open(const std::string &dirtab_path) {
22  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  FILE *dirtab_file = fopen(dirtab_path.c_str(), "r");
30  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  valid_ = Parse(dirtab_file);
39  fclose(dirtab_file);
40  return valid_;
41 }
42 
43 bool Dirtab::Parse(const std::string &dirtab) {
44  valid_ = true;
45  off_t line_offset = 0;
46  while (line_offset < static_cast<off_t>(dirtab.size())) {
47  std::string line = GetLineMem(dirtab.c_str() + line_offset,
48  dirtab.size() - line_offset);
49  line_offset += line.size() + 1; // +1 == skipped \n
50  if (!ParseLine(line)) {
51  valid_ = false;
52  }
53  }
55  return valid_;
56 }
57 
58 
59 bool Dirtab::Parse(FILE *dirtab_file) {
60  valid_ = true;
61  std::string line;
62  while (GetLineFile(dirtab_file, &line)) {
63  if (!ParseLine(line)) {
64  valid_ = false;
65  }
66  }
68  return valid_;
69 }
70 
71 
72 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  std::string::const_iterator itr = line.begin();
77  const std::string::const_iterator iend = line.end();
78  bool negation = false;
79 
80  // parse preamble
81  SkipWhitespace(iend, &itr);
82  if (*itr == Dirtab::kCommentMarker) {
83  return true;
84  } else if (*itr == Dirtab::kNegationMarker) {
85  negation = true;
86  ++itr;
87  SkipWhitespace(iend, &itr);
88  }
89 
90  // extract and parse pathspec
91  std::string pathspec_str(Trim(std::string(itr, iend)));
92  return this->ParsePathspec(pathspec_str, negation);
93 }
94 
95 bool Dirtab::ParsePathspec(const std::string &pathspec_str, bool negation) {
96  if (pathspec_str.empty()) {
97  return true;
98  }
99  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  if ( !pathspec.IsValid() ||
104  (!negation && !pathspec.IsAbsolute())) {
105  return false;
106  }
107 
108  // create a new dirtab rule
109  const Rule rule(pathspec, negation);
110  AddRule(rule);
111  return true;
112 }
113 
114 
115 void Dirtab::AddRule(const Rule &rule) {
116  if (rule.is_negation) {
117  negative_rules_.push_back(rule);
118  } else {
119  positive_rules_.push_back(rule);
120  }
121 }
122 
123 
125  // check if there are contradicting positive and negative rules
126  Rules::const_iterator p = positive_rules_.begin();
127  const Rules::const_iterator pend = positive_rules_.end();
128  for (; p != pend; ++p) {
129  assert(!p->is_negation);
130  Rules::const_iterator n = negative_rules_.begin();
131  const Rules::const_iterator nend = negative_rules_.end();
132  for (; n != nend; ++n) {
133  assert(n->is_negation);
134  if (p->pathspec == n->pathspec) {
135  return false;
136  }
137  }
138  }
139 
140  return true;
141 }
142 
143 
144 bool Dirtab::IsMatching(const std::string &path) const {
145  // check if path has a positive match
146  bool has_positive_match = false;
147  Rules::const_iterator p = positive_rules_.begin();
148  const Rules::const_iterator pend = positive_rules_.end();
149  for (; p != pend; ++p) {
150  assert(!p->is_negation);
151  if (p->pathspec.IsMatching(path)) {
152  has_positive_match = true;
153  break;
154  }
155  }
156 
157  return has_positive_match && !IsOpposing(path);
158 }
159 
160 
161 bool Dirtab::IsOpposing(const std::string &path) const {
162  Rules::const_iterator n = negative_rules_.begin();
163  const Rules::const_iterator nend = negative_rules_.end();
164  for (; n != nend; ++n) {
165  assert(n->is_negation);
166  if (n->pathspec.IsMatchingRelaxed(path)) {
167  return true;
168  }
169  }
170 
171  return false;
172 }
173 
174 } // namespace catalog
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
virtual bool IsMatching(const std::string &path) const
Definition: dirtab.cc:144
string GetLineMem(const char *text, const int text_size)
Definition: string.cc:372
bool Open(const std::string &dirtab_path)
Definition: dirtab.cc:21
string Trim(const string &raw, bool trim_newline)
Definition: string.cc:420
Rules positive_rules_
Definition: dirtab.h:149
void SkipWhitespace(const std::string::const_iterator &end, std::string::const_iterator *itr) const
Definition: dirtab.h:139
bool ParseLine(const std::string &line)
Definition: dirtab.cc:72
assert((mem||(size==0))&&"Out Of Memory")
static const char kCommentMarker
Definition: dirtab.h:53
bool IsValid() const
Definition: pathspec.h:106
virtual bool IsOpposing(const std::string &path) const
Definition: dirtab.cc:161
bool FileExists(const std::string &path)
Definition: posix.cc:811
bool GetLineFile(FILE *f, std::string *line)
Definition: string.cc:378
bool IsAbsolute() const
Definition: pathspec.h:112
virtual bool ParsePathspec(const std::string &pathspec_str, bool negation)
Definition: dirtab.cc:95
void AddRule(const Rule &rule)
Definition: dirtab.cc:115
Rules negative_rules_
Definition: dirtab.h:150
virtual bool Parse(const std::string &dirtab)
Definition: dirtab.cc:43
bool CheckRuleValidity() const
Definition: dirtab.cc:124
static const char kNegationMarker
Definition: dirtab.h:54