GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/uid_map.h
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 66 67 98.5%
Branches: 60 87 69.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_UID_MAP_H_
6 #define CVMFS_UID_MAP_H_
7
8 #include <sys/types.h>
9
10 #include <cerrno>
11 #include <map>
12 #include <string>
13 #include <vector>
14
15 #include "sanitizer.h"
16 #include "util/logging.h"
17 #include "util/string.h"
18
19 /**
20 * This reads a mapping file of (roughly) the following format:
21 * +-------------------------------------------------------------+
22 * | user_id.map |
23 * | ~~~~~~~~~~~ |
24 * | |
25 * | # map UIDs 137 and 138 to 1000 (I am a comment by the way) |
26 * | 137 1000 |
27 * | 138 1000 |
28 * | |
29 * | # swap two UIDs |
30 * | 101 5 |
31 * | 5 101 |
32 * | |
33 * | # map everything else to root (wildcard) |
34 * | * 0 |
35 * +-------------------------------------------------------------+
36 *
37 * These files are intended for the definition of UID and GID mappings both on
38 * the client and the server side of CernVM-FS.
39 *
40 * The class takes care of managing these mappings and can be initialised via
41 * a file read from disk or programmatically through the class's public API.
42 * When reading from a file, simple consistency checks are performed to ensure
43 * proper functionality.
44 */
45 template <typename T>
46 class IntegerMap {
47 public:
48 typedef T key_type;
49 typedef T value_type;
50 typedef typename std::map<key_type, value_type> map_type;
51
52 public:
53 234 IntegerMap()
54 234 : valid_(true)
55 234 , has_default_value_(false)
56 234 , default_value_(T(0)) {}
57
58 /**
59 * Define a mapping from k to v
60 * @param k map the given value to v
61 * @param v the value given in k is mapped to this
62 **/
63 24 void Set(const T k, const T v) { map_[k] = v; }
64
65 /**
66 * Sets a default (or fallback) value to be used if no other mapping rule fits
67 * Note: A previously defined default value is overwritten.
68 * @param v the value to be used as a fallback in Map()
69 */
70 10 void SetDefault(const T v) {
71 10 has_default_value_ = true;
72 10 default_value_ = v;
73 10 }
74
75 /**
76 * Reads mapping rules from a provided file path. The file format is discussed
77 * in the class description above.
78 * Note: If a read failure occurs the IntegerMap<> is declared invalid and
79 * must not be used anymore.
80 *
81 * @param path the file path to be read
82 * @return true if the file was successfully read
83 */
84 9 bool Read(const std::string &path) {
85 9 valid_ = ReadFromFile(path);
86 9 return IsValid();
87 }
88
89 /**
90 * Checks if a mapping rule for a given value is available
91 * @param k the value to be checked
92 * @return true if a mapping rule for k exists
93 */
94 16 bool Contains(const T k) const {
95
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 assert(IsValid());
96
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 return map_.find(k) != map_.end();
97 }
98
99 /**
100 * Applies the mapping rules inside this IntegerMap<> to the given value.
101 * @param k the value to be mapped
102 * @return the result of the mapping rule application (might be the default)
103 */
104 22 T Map(const T k) const {
105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 assert(IsValid());
106
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 typename map_type::const_iterator i = map_.find(k);
107
2/2
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 10 times.
22 if (i != map_.end()) {
108 12 return i->second;
109 }
110
111 10 return (HasDefault())
112
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 ? default_value_
113 10 : k;
114 }
115
116 210 bool HasEffect() const {
117
4/4
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 206 times.
210 return (map_.size() != 0) || has_default_value_;
118 }
119
120 8 bool IsEmpty() const { return map_.size() == 0; }
121 61 bool IsValid() const { return valid_; }
122 18 bool HasDefault() const { return has_default_value_; }
123 8 size_t RuleCount() const { return map_.size(); }
124
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 T GetDefault() const { assert(has_default_value_); return default_value_; }
126 const map_type& GetRuleMap() const { return map_; }
127
128 protected:
129 9 bool ReadFromFile(const std::string &path) {
130
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 FILE *fmap = fopen(path.c_str(), "r");
131
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (!fmap) {
132
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 LogCvmfs(kLogUtility, kLogDebug, "failed to open %s (errno: %d)",
133 1 path.c_str(), errno);
134 1 return false;
135 }
136
137
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 sanitizer::IntegerSanitizer int_sanitizer;
138
139 8 std::string line;
140 8 unsigned int line_number = 0;
141
6/7
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 28 times.
✓ Branch 8 taken 2 times.
46 while (GetLineFile(fmap, &line)) {
142 28 ++line_number;
143
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 line = Trim(line);
144
7/8
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 16 times.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 16 times.
28 if (line.empty() || line[0] == '#') {
145 14 continue;
146 }
147
148
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 std::vector<std::string> components = SplitString(line, ' ');
149
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 FilterEmptyStrings(&components);
150 16 if (components.size() != 2 ||
151
7/10
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 10 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
28 !int_sanitizer.IsValid(components[1]) ||
152
6/10
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 8 times.
12 (components[0] != "*" && !int_sanitizer.IsValid(components[0]))) {
153
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 fclose(fmap);
154
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 LogCvmfs(kLogUtility, kLogDebug, "failed to read line %d in %s",
155 line_number, path.c_str());
156 6 return false;
157 }
158
159
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 value_type to = String2Uint64(components[1]);
160
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
10 if (components[0] == "*") {
161 2 SetDefault(to);
162 2 continue;
163 }
164
165
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 key_type from = String2Uint64(components[0]);
166
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 Set(from, to);
167 }
168
169
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 fclose(fmap);
170 2 return true;
171 8 }
172
173 16 void FilterEmptyStrings(std::vector<std::string> *vec) const {
174 16 std::vector<std::string>::iterator i = vec->begin();
175
2/2
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 16 times.
52 for (; i != vec->end(); ) {
176
3/4
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 30 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
36 i = (i->empty()) ? vec->erase(i) : i + 1;
177 }
178 16 }
179
180 private:
181 bool valid_;
182 map_type map_;
183
184 bool has_default_value_;
185 T default_value_;
186 };
187
188 typedef IntegerMap<uid_t> UidMap;
189 typedef IntegerMap<gid_t> GidMap;
190
191 #endif // CVMFS_UID_MAP_H_
192