CernVM-FS  2.13.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 "util/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) {
32  "Cannot open dirtab for reading at '%s' "
33  "(errno: %d)",
34  dirtab_path.c_str(), errno);
35  valid_ = false;
36  return valid_;
37  }
38 
39  valid_ = Parse(dirtab_file);
40  fclose(dirtab_file);
41  return valid_;
42 }
43 
44 bool Dirtab::Parse(const std::string &dirtab) {
45  valid_ = true;
46  off_t line_offset = 0;
47  while (line_offset < static_cast<off_t>(dirtab.size())) {
48  std::string line = GetLineMem(dirtab.c_str() + line_offset,
49  dirtab.size() - line_offset);
50  line_offset += line.size() + 1; // +1 == skipped \n
51  if (!ParseLine(line)) {
52  valid_ = false;
53  }
54  }
56  return valid_;
57 }
58 
59 
60 bool Dirtab::Parse(FILE *dirtab_file) {
61  valid_ = true;
62  std::string line;
63  while (GetLineFile(dirtab_file, &line)) {
64  if (!ParseLine(line)) {
65  valid_ = false;
66  }
67  }
69  return valid_;
70 }
71 
72 
73 bool Dirtab::ParseLine(const std::string &line) {
74  // line parsing is done using std::string iterators. Each parsing method ex-
75  // pects an iterator and the end iterator. While parsing itr is constantly
76  // incremented to walk through the given .cvmfsdirtab line.
77  std::string::const_iterator itr = line.begin();
78  const std::string::const_iterator iend = line.end();
79  bool negation = false;
80 
81  // parse preamble
82  SkipWhitespace(iend, &itr);
83  if (*itr == Dirtab::kCommentMarker) {
84  return true;
85  } else if (*itr == Dirtab::kNegationMarker) {
86  negation = true;
87  ++itr;
88  SkipWhitespace(iend, &itr);
89  }
90 
91  // extract and parse pathspec
92  std::string pathspec_str(Trim(std::string(itr, iend)));
93  return this->ParsePathspec(pathspec_str, negation);
94 }
95 
96 bool Dirtab::ParsePathspec(const std::string &pathspec_str, bool negation) {
97  if (pathspec_str.empty()) {
98  return true;
99  }
100  Pathspec pathspec(pathspec_str);
101 
102  // all generated Pathspecs need to be valid and positive rules must be
103  // absolute. Otherwise the .cvmfsdirtab is not valid.
104  if (!pathspec.IsValid() || (!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
virtual bool IsMatching(const std::string &path) const
Definition: dirtab.cc:144
string GetLineMem(const char *text, const int text_size)
Definition: string.cc:415
bool Open(const std::string &dirtab_path)
Definition: dirtab.cc:21
string Trim(const string &raw, bool trim_newline)
Definition: string.cc:466
Rules positive_rules_
Definition: dirtab.h:148
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:73
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:803
bool GetLineFile(FILE *f, std::string *line)
Definition: string.cc:422
bool IsAbsolute() const
Definition: pathspec.h:112
virtual bool ParsePathspec(const std::string &pathspec_str, bool negation)
Definition: dirtab.cc:96
void AddRule(const Rule &rule)
Definition: dirtab.cc:115
Rules negative_rules_
Definition: dirtab.h:149
virtual bool Parse(const std::string &dirtab)
Definition: dirtab.cc:44
bool CheckRuleValidity() const
Definition: dirtab.cc:124
static const char kNegationMarker
Definition: dirtab.h:54
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545