GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 "logging.h" |
||
16 |
#include "sanitizer.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 |
447 |
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 |
337 |
IntegerMap() |
|
54 |
: valid_(true) |
||
55 |
, has_default_value_(false) |
||
56 |
337 |
, 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 |
60 |
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 |
25 |
void SetDefault(const T v) { |
|
71 |
25 |
has_default_value_ = true; |
|
72 |
25 |
default_value_ = v; |
|
73 |
25 |
} |
|
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 |
22 |
bool Read(const std::string &path) { |
|
85 |
22 |
valid_ = ReadFromFile(path); |
|
86 |
22 |
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 |
40 |
bool Contains(const T k) const { |
|
95 |
✗✓ | 40 |
assert(IsValid()); |
96 |
40 |
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 |
55 |
T Map(const T k) const { |
|
105 |
✗✓ | 55 |
assert(IsValid()); |
106 |
55 |
typename map_type::const_iterator i = map_.find(k); |
|
107 |
✓✓ | 55 |
if (i != map_.end()) { |
108 |
30 |
return i->second; |
|
109 |
} |
||
110 |
|||
111 |
return (HasDefault()) |
||
112 |
? default_value_ |
||
113 |
✓✓ | 25 |
: k; |
114 |
} |
||
115 |
|||
116 |
158 |
bool HasEffect() const { |
|
117 |
✓✓✓✓ |
158 |
return (map_.size() != 0) || has_default_value_; |
118 |
} |
||
119 |
|||
120 |
20 |
bool IsEmpty() const { return map_.size() == 0; } |
|
121 |
152 |
bool IsValid() const { return valid_; } |
|
122 |
45 |
bool HasDefault() const { return has_default_value_; } |
|
123 |
20 |
size_t RuleCount() const { return map_.size(); } |
|
124 |
|||
125 |
✗✓ | 10 |
T GetDefault() const { assert(has_default_value_); return default_value_; } |
126 |
const map_type& GetRuleMap() const { return map_; } |
||
127 |
|||
128 |
protected: |
||
129 |
22 |
bool ReadFromFile(const std::string &path) { |
|
130 |
22 |
FILE *fmap = fopen(path.c_str(), "r"); |
|
131 |
✓✓ | 22 |
if (!fmap) { |
132 |
2 |
LogCvmfs(kLogUtility, kLogDebug, "failed to open %s (errno: %d)", |
|
133 |
path.c_str(), errno); |
||
134 |
2 |
return false; |
|
135 |
} |
||
136 |
|||
137 |
20 |
sanitizer::IntegerSanitizer int_sanitizer; |
|
138 |
|||
139 |
20 |
std::string line; |
|
140 |
20 |
unsigned int line_number = 0; |
|
141 |
✗✓✓✗ ✓✓ |
20 |
while (GetLineFile(fmap, &line)) { |
142 |
70 |
++line_number; |
|
143 |
70 |
line = Trim(line); |
|
144 |
✓✓✓✓ ✓✓ |
70 |
if (line.empty() || line[0] == '#') { |
145 |
30 |
continue; |
|
146 |
} |
||
147 |
|||
148 |
40 |
std::vector<std::string> components = SplitString(line, ' '); |
|
149 |
40 |
FilterEmptyStrings(&components); |
|
150 |
✓✓✓✓ ✓✓✓✓ ✓✓ |
40 |
if (components.size() != 2 || |
151 |
!int_sanitizer.IsValid(components[1]) || |
||
152 |
(components[0] != "*" && !int_sanitizer.IsValid(components[0]))) { |
||
153 |
15 |
fclose(fmap); |
|
154 |
15 |
LogCvmfs(kLogUtility, kLogDebug, "failed to read line %d in %s", |
|
155 |
line_number, path.c_str()); |
||
156 |
15 |
return false; |
|
157 |
} |
||
158 |
|||
159 |
25 |
value_type to = String2Uint64(components[1]); |
|
160 |
✓✓ | 25 |
if (components[0] == "*") { |
161 |
5 |
SetDefault(to); |
|
162 |
5 |
continue; |
|
163 |
} |
||
164 |
|||
165 |
20 |
key_type from = String2Uint64(components[0]); |
|
166 |
20 |
Set(from, to); |
|
167 |
} |
||
168 |
|||
169 |
5 |
fclose(fmap); |
|
170 |
5 |
return true; |
|
171 |
} |
||
172 |
|||
173 |
40 |
void FilterEmptyStrings(std::vector<std::string> *vec) const { |
|
174 |
40 |
std::vector<std::string>::iterator i = vec->begin(); |
|
175 |
✓✓ | 170 |
for (; i != vec->end(); ) { |
176 |
✓✓ | 90 |
i = (i->empty()) ? vec->erase(i) : i + 1; |
177 |
} |
||
178 |
40 |
} |
|
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_ |
Generated by: GCOVR (Version 4.1) |