GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/uid_map.h
Date: 2026-10-25 02:40:14
Exec Total Coverage
Lines: 62 63 98.4%
Branches: 60 85 70.6%

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