GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/uid_map.h
Date: 2025-06-01 02:36:00
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 <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 240 IntegerMap()
54 240 : valid_(true), has_default_value_(false), default_value_(T(0)) { }
55
56 /**
57 * Define a mapping from k to v
58 * @param k map the given value to v
59 * @param v the value given in k is mapped to this
60 **/
61 24 void Set(const T k, const T v) { map_[k] = v; }
62
63 /**
64 * Sets a default (or fallback) value to be used if no other mapping rule fits
65 * Note: A previously defined default value is overwritten.
66 * @param v the value to be used as a fallback in Map()
67 */
68 10 void SetDefault(const T v) {
69 10 has_default_value_ = true;
70 10 default_value_ = v;
71 10 }
72
73 /**
74 * Reads mapping rules from a provided file path. The file format is discussed
75 * in the class description above.
76 * Note: If a read failure occurs the IntegerMap<> is declared invalid and
77 * must not be used anymore.
78 *
79 * @param path the file path to be read
80 * @return true if the file was successfully read
81 */
82 9 bool Read(const std::string &path) {
83 9 valid_ = ReadFromFile(path);
84 9 return IsValid();
85 }
86
87 /**
88 * Checks if a mapping rule for a given value is available
89 * @param k the value to be checked
90 * @return true if a mapping rule for k exists
91 */
92 16 bool Contains(const T k) const {
93
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 assert(IsValid());
94
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 return map_.find(k) != map_.end();
95 }
96
97 /**
98 * Applies the mapping rules inside this IntegerMap<> to the given value.
99 * @param k the value to be mapped
100 * @return the result of the mapping rule application (might be the default)
101 */
102 22 T Map(const T k) const {
103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 assert(IsValid());
104
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 typename map_type::const_iterator i = map_.find(k);
105
2/2
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 10 times.
22 if (i != map_.end()) {
106 12 return i->second;
107 }
108
109
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
10 return (HasDefault()) ? default_value_ : k;
110 }
111
112
4/4
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 226 times.
230 bool HasEffect() const { return (map_.size() != 0) || has_default_value_; }
113
114 8 bool IsEmpty() const { return map_.size() == 0; }
115 61 bool IsValid() const { return valid_; }
116 18 bool HasDefault() const { return has_default_value_; }
117 8 size_t RuleCount() const { return map_.size(); }
118
119 4 T GetDefault() const {
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(has_default_value_);
121 4 return default_value_;
122 }
123 const map_type &GetRuleMap() const { return map_; }
124
125 protected:
126 9 bool ReadFromFile(const std::string &path) {
127
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 FILE *fmap = fopen(path.c_str(), "r");
128
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (!fmap) {
129
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 LogCvmfs(kLogUtility, kLogDebug, "failed to open %s (errno: %d)",
130 1 path.c_str(), errno);
131 1 return false;
132 }
133
134
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 sanitizer::IntegerSanitizer int_sanitizer;
135
136 8 std::string line;
137 8 unsigned int line_number = 0;
138
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)) {
139 28 ++line_number;
140
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 line = Trim(line);
141
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] == '#') {
142 14 continue;
143 }
144
145
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 std::vector<std::string> components = SplitString(line, ' ');
146
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 FilterEmptyStrings(&components);
147
3/4
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 2 times.
30 if (components.size() != 2 || !int_sanitizer.IsValid(components[1])
148
10/14
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 8 times.
✓ Branch 14 taken 6 times.
✓ Branch 15 taken 10 times.
30 || (components[0] != "*" && !int_sanitizer.IsValid(components[0]))) {
149
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 fclose(fmap);
150
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 LogCvmfs(kLogUtility, kLogDebug, "failed to read line %d in %s",
151 line_number, path.c_str());
152 6 return false;
153 }
154
155
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 value_type to = String2Uint64(components[1]);
156
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
10 if (components[0] == "*") {
157 2 SetDefault(to);
158 2 continue;
159 }
160
161
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 key_type from = String2Uint64(components[0]);
162
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 Set(from, to);
163 }
164
165
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 fclose(fmap);
166 2 return true;
167 8 }
168
169 16 void FilterEmptyStrings(std::vector<std::string> *vec) const {
170 16 std::vector<std::string>::iterator i = vec->begin();
171
2/2
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 16 times.
52 for (; i != vec->end();) {
172
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;
173 }
174 16 }
175
176 private:
177 bool valid_;
178 map_type map_;
179
180 bool has_default_value_;
181 T default_value_;
182 };
183
184 typedef IntegerMap<uid_t> UidMap;
185 typedef IntegerMap<gid_t> GidMap;
186
187 #endif // CVMFS_UID_MAP_H_
188