GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/** |
||
2 |
* This file is part of the CernVM File System. |
||
3 |
* |
||
4 |
* Fills an internal map of key-value pairs from ASCII files in key=value |
||
5 |
* style. Parameters can be overwritten. Used to read configuration from |
||
6 |
* /etc/cvmfs/... |
||
7 |
*/ |
||
8 |
|||
9 |
#include "cvmfs_config.h" |
||
10 |
#include "options.h" |
||
11 |
|||
12 |
#include <fcntl.h> |
||
13 |
#include <sys/wait.h> |
||
14 |
#include <unistd.h> |
||
15 |
|||
16 |
#include <cassert> |
||
17 |
#include <cstdio> |
||
18 |
#include <cstdlib> |
||
19 |
#include <utility> |
||
20 |
|||
21 |
#include "logging.h" |
||
22 |
#include "sanitizer.h" |
||
23 |
#include "util/posix.h" |
||
24 |
#include "util/string.h" |
||
25 |
|||
26 |
using namespace std; // NOLINT |
||
27 |
|||
28 |
#ifdef CVMFS_NAMESPACE_GUARD |
||
29 |
namespace CVMFS_NAMESPACE_GUARD { |
||
30 |
#endif |
||
31 |
|||
32 |
|||
33 |
934 |
static string EscapeShell(const std::string &raw) { |
|
34 |
✓✓ | 13145 |
for (unsigned i = 0, l = raw.length(); i < l; ++i) { |
35 |
✓✓✓✓ ✓✓✓✓ ✓✓✗✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✓✓ |
12217 |
if (!(((raw[i] >= '0') && (raw[i] <= '9')) || |
36 |
((raw[i] >= 'A') && (raw[i] <= 'Z')) || |
||
37 |
((raw[i] >= 'a') && (raw[i] <= 'z')) || |
||
38 |
(raw[i] == '/') || (raw[i] == ':') || (raw[i] == '.') || |
||
39 |
(raw[i] == '_') || (raw[i] == '-') || (raw[i] == ','))) |
||
40 |
{ |
||
41 |
6 |
goto escape_shell_quote; |
|
42 |
} |
||
43 |
} |
||
44 |
928 |
return raw; |
|
45 |
|||
46 |
escape_shell_quote: |
||
47 |
6 |
string result = "'"; |
|
48 |
✓✓ | 296 |
for (unsigned i = 0, l = raw.length(); i < l; ++i) { |
49 |
✗✓ | 290 |
if (raw[i] == '\'') |
50 |
result += "\\"; |
||
51 |
290 |
result += raw[i]; |
|
52 |
} |
||
53 |
6 |
result += "'"; |
|
54 |
6 |
return result; |
|
55 |
} |
||
56 |
|||
57 |
|||
58 |
1087 |
string OptionsManager::TrimParameter(const string ¶meter) { |
|
59 |
1087 |
string result = Trim(parameter); |
|
60 |
// Strip "readonly" |
||
61 |
✗✓ | 1087 |
if (result.find("readonly ") == 0) { |
62 |
result = result.substr(9); |
||
63 |
result = Trim(result); |
||
64 |
✓✓ | 1087 |
} else if (result.find("export ") == 0) { |
65 |
12 |
result = result.substr(7); |
|
66 |
12 |
result = Trim(result); |
|
67 |
✗✓ | 1075 |
} else if (result.find("eval ") == 0) { |
68 |
result = result.substr(5); |
||
69 |
result = Trim(result); |
||
70 |
} |
||
71 |
1087 |
return result; |
|
72 |
} |
||
73 |
|||
74 |
10 |
void OptionsManager::SwitchTemplateManager( |
|
75 |
OptionsTemplateManager *opt_templ_mgr_param) { |
||
76 |
✓✗ | 10 |
delete opt_templ_mgr_; |
77 |
✓✗ | 10 |
if (opt_templ_mgr_param != NULL) { |
78 |
10 |
opt_templ_mgr_ = opt_templ_mgr_param; |
|
79 |
} else { |
||
80 |
opt_templ_mgr_ = new OptionsTemplateManager(); |
||
81 |
} |
||
82 |
✓✓ | 14 |
for (std::map<std::string, std::string>::iterator it |
83 |
10 |
= templatable_values_.begin(); |
|
84 |
it != templatable_values_.end(); |
||
85 |
it++) { |
||
86 |
4 |
config_[it->first].value = it->second; |
|
87 |
4 |
opt_templ_mgr_->ParseString(&(config_[it->first].value)); |
|
88 |
4 |
UpdateEnvironment(it->first, config_[it->first]); |
|
89 |
} |
||
90 |
10 |
} |
|
91 |
|||
92 |
|||
93 |
9 |
bool SimpleOptionsParser::TryParsePath(const string &config_file) { |
|
94 |
LogCvmfs(kLogCvmfs, kLogDebug, "Fast-parsing config file %s", |
||
95 |
9 |
config_file.c_str()); |
|
96 |
9 |
string line; |
|
97 |
9 |
FILE *fconfig = fopen(config_file.c_str(), "r"); |
|
98 |
✓✓ | 9 |
if (fconfig == NULL) |
99 |
1 |
return false; |
|
100 |
|||
101 |
// Read line by line and extract parameters |
||
102 |
✗✗✓✓ ✗✓✓ |
8 |
while (GetLineFile(fconfig, &line)) { |
103 |
116 |
size_t comment_idx = line.find("#"); |
|
104 |
✓✓ | 116 |
if (comment_idx != string::npos) |
105 |
12 |
line = line.substr(0, comment_idx); |
|
106 |
116 |
line = Trim(line); |
|
107 |
✓✓ | 116 |
if (line.empty()) |
108 |
12 |
continue; |
|
109 |
104 |
vector<string> tokens = SplitString(line, '='); |
|
110 |
✓✓ | 104 |
if (tokens.size() < 2) |
111 |
6 |
continue; |
|
112 |
98 |
string parameter = TrimParameter(tokens[0]); |
|
113 |
✗✓ | 98 |
if (parameter.find(" ") != string::npos) |
114 |
continue; |
||
115 |
✓✓ | 98 |
if (parameter.empty()) |
116 |
12 |
continue; |
|
117 |
|||
118 |
// Strip quotes from value |
||
119 |
86 |
tokens.erase(tokens.begin()); |
|
120 |
86 |
string value = Trim(JoinStrings(tokens, "=")); |
|
121 |
86 |
unsigned value_length = value.length(); |
|
122 |
✓✓ | 86 |
if (value_length > 2) { |
123 |
✓✓✗✓ ✓✓✓✗ ✓✓ |
62 |
if ( ((value[0] == '"') && ((value[value_length - 1] == '"'))) || |
124 |
((value[0] == '\'') && ((value[value_length - 1] == '\''))) ) |
||
125 |
{ |
||
126 |
12 |
value = value.substr(1, value_length - 2); |
|
127 |
} |
||
128 |
} |
||
129 |
|||
130 |
86 |
ConfigValue config_value; |
|
131 |
86 |
config_value.source = config_file; |
|
132 |
86 |
config_value.value = value; |
|
133 |
86 |
PopulateParameter(parameter, config_value); |
|
134 |
} |
||
135 |
8 |
fclose(fconfig); |
|
136 |
8 |
return true; |
|
137 |
} |
||
138 |
|||
139 |
108 |
void BashOptionsManager::ParsePath(const string &config_file, |
|
140 |
const bool external) { |
||
141 |
108 |
LogCvmfs(kLogCvmfs, kLogDebug, "Parsing config file %s", config_file.c_str()); |
|
142 |
int retval; |
||
143 |
int pipe_open[2]; |
||
144 |
int pipe_quit[2]; |
||
145 |
108 |
pid_t pid_child = 0; |
|
146 |
✗✓ | 108 |
if (external) { |
147 |
// cvmfs can run in the process group of automount in which case |
||
148 |
// autofs won't mount an additional config repository. We create a |
||
149 |
// short-lived process that detaches from the process group and triggers |
||
150 |
// autofs to mount the config repository, if necessary. It holds a file |
||
151 |
// handle to the config file until the main process opened the file, too. |
||
152 |
MakePipe(pipe_open); |
||
153 |
MakePipe(pipe_quit); |
||
154 |
switch (pid_child = fork()) { |
||
155 |
case -1: |
||
156 |
abort(); |
||
157 |
case 0: { // Child |
||
158 |
close(pipe_open[0]); |
||
159 |
close(pipe_quit[1]); |
||
160 |
// If this is not a process group leader, create a new session |
||
161 |
if (getpgrp() != getpid()) { |
||
162 |
pid_t new_session = setsid(); |
||
163 |
assert(new_session != (pid_t)-1); |
||
164 |
} |
||
165 |
(void)open(config_file.c_str(), O_RDONLY); |
||
166 |
char ready = 'R'; |
||
167 |
WritePipe(pipe_open[1], &ready, 1); |
||
168 |
retval = read(pipe_quit[0], &ready, 1); |
||
169 |
_exit(retval); // Don't flush shared file descriptors |
||
170 |
} |
||
171 |
} |
||
172 |
// Parent |
||
173 |
close(pipe_open[1]); |
||
174 |
close(pipe_quit[0]); |
||
175 |
char ready = 0; |
||
176 |
ReadPipe(pipe_open[0], &ready, 1); |
||
177 |
assert(ready == 'R'); |
||
178 |
close(pipe_open[0]); |
||
179 |
} |
||
180 |
108 |
const string config_path = GetParentPath(config_file); |
|
181 |
108 |
FILE *fconfig = fopen(config_file.c_str(), "r"); |
|
182 |
✗✓ | 108 |
if (pid_child > 0) { |
183 |
char c = 'C'; |
||
184 |
WritePipe(pipe_quit[1], &c, 1); |
||
185 |
int statloc; |
||
186 |
waitpid(pid_child, &statloc, 0); |
||
187 |
close(pipe_quit[1]); |
||
188 |
} |
||
189 |
✓✓ | 108 |
if (!fconfig) { |
190 |
✗✓✗✗ ✗✓ |
1 |
if (external && !DirectoryExists(config_path)) { |
191 |
string repo_required; |
||
192 |
if (GetValue("CVMFS_CONFIG_REPO_REQUIRED", &repo_required) && |
||
193 |
IsOn(repo_required)) { |
||
194 |
LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, |
||
195 |
"required configuration repository directory does not exist: %s", |
||
196 |
config_path.c_str()); |
||
197 |
// Do not crash as in abort(), which can trigger core file creation |
||
198 |
// from the mount helper |
||
199 |
exit(1); |
||
200 |
} |
||
201 |
|||
202 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogWarn, |
||
203 |
"configuration repository directory does not exist: %s", |
||
204 |
config_path.c_str()); |
||
205 |
} |
||
206 |
return; |
||
207 |
} |
||
208 |
|||
209 |
int fd_stdin; |
||
210 |
int fd_stdout; |
||
211 |
int fd_stderr; |
||
212 |
107 |
retval = Shell(&fd_stdin, &fd_stdout, &fd_stderr); |
|
213 |
✗✓ | 107 |
assert(retval); |
214 |
|||
215 |
// Let the shell read the file |
||
216 |
107 |
string line; |
|
217 |
107 |
const string newline = "\n"; |
|
218 |
const string cd = "cd \"" + ((config_path == "") ? "/" : config_path) + "\"" + |
||
219 |
✗✓✗✗ ✗✗✗✓ |
107 |
newline; |
220 |
107 |
WritePipe(fd_stdin, cd.data(), cd.length()); |
|
221 |
✓✓ | 1221 |
while (GetLineFile(fconfig, &line)) { |
222 |
1007 |
WritePipe(fd_stdin, line.data(), line.length()); |
|
223 |
1007 |
WritePipe(fd_stdin, newline.data(), newline.length()); |
|
224 |
} |
||
225 |
107 |
rewind(fconfig); |
|
226 |
|||
227 |
// Read line by line and extract parameters |
||
228 |
✗✗✓✓ ✗✓✓✗ ✓✓ |
107 |
while (GetLineFile(fconfig, &line)) { |
229 |
1007 |
line = Trim(line); |
|
230 |
✓✓✓✓ ✗✓✓✓ |
1007 |
if (line.empty() || line[0] == '#' || line.find("if ") == 0) |
231 |
12 |
continue; |
|
232 |
995 |
vector<string> tokens = SplitString(line, '='); |
|
233 |
✓✓ | 995 |
if (tokens.size() < 2) |
234 |
6 |
continue; |
|
235 |
|||
236 |
989 |
ConfigValue value; |
|
237 |
989 |
value.source = config_file; |
|
238 |
989 |
string parameter = TrimParameter(tokens[0]); |
|
239 |
✓✓ | 989 |
if (parameter.empty()) |
240 |
12 |
continue; |
|
241 |
|||
242 |
977 |
const string sh_echo = "echo $" + parameter + "\n"; |
|
243 |
977 |
WritePipe(fd_stdin, sh_echo.data(), sh_echo.length()); |
|
244 |
977 |
GetLineFd(fd_stdout, &value.value); |
|
245 |
977 |
PopulateParameter(parameter, value); |
|
246 |
} |
||
247 |
|||
248 |
107 |
close(fd_stderr); |
|
249 |
107 |
close(fd_stdout); |
|
250 |
107 |
close(fd_stdin); |
|
251 |
107 |
fclose(fconfig); |
|
252 |
} |
||
253 |
|||
254 |
|||
255 |
59 |
bool OptionsManager::HasConfigRepository(const string &fqrn, |
|
256 |
string *config_path) { |
||
257 |
59 |
string cvmfs_mount_dir; |
|
258 |
✓✗✗✗ |
59 |
if (!GetValue("CVMFS_MOUNT_DIR", &cvmfs_mount_dir)) { |
259 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "CVMFS_MOUNT_DIR missing"); |
||
260 |
return false; |
||
261 |
} |
||
262 |
|||
263 |
59 |
string config_repository; |
|
264 |
✓✗✗✓ |
59 |
if (GetValue("CVMFS_CONFIG_REPOSITORY", &config_repository)) { |
265 |
✓✗✗✓ ✗✓ |
9 |
if (config_repository.empty() || (config_repository == fqrn)) |
266 |
return false; |
||
267 |
9 |
sanitizer::RepositorySanitizer repository_sanitizer; |
|
268 |
✗✓ | 9 |
if (!repository_sanitizer.IsValid(config_repository)) { |
269 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, |
||
270 |
"invalid CVMFS_CONFIG_REPOSITORY: %s", |
||
271 |
config_repository.c_str()); |
||
272 |
return false; |
||
273 |
} |
||
274 |
9 |
*config_path = cvmfs_mount_dir + "/" + config_repository + "/etc/cvmfs/"; |
|
275 |
9 |
return true; |
|
276 |
} |
||
277 |
50 |
return false; |
|
278 |
} |
||
279 |
|||
280 |
|||
281 |
void OptionsManager::ParseDefault(const string &fqrn) { |
||
282 |
if (taint_environment_) { |
||
283 |
int retval = setenv("CVMFS_FQRN", fqrn.c_str(), 1); |
||
284 |
assert(retval == 0); |
||
285 |
} |
||
286 |
|||
287 |
protected_parameters_.clear(); |
||
288 |
ParsePath("/etc/cvmfs/default.conf", false); |
||
289 |
vector<string> dist_defaults = |
||
290 |
FindFilesBySuffix("/etc/cvmfs/default.d", ".conf"); |
||
291 |
for (unsigned i = 0; i < dist_defaults.size(); ++i) { |
||
292 |
ParsePath(dist_defaults[i], false); |
||
293 |
} |
||
294 |
ProtectParameter("CVMFS_CONFIG_REPOSITORY"); |
||
295 |
string external_config_path; |
||
296 |
if ((fqrn != "") && HasConfigRepository(fqrn, &external_config_path)) |
||
297 |
ParsePath(external_config_path + "default.conf", true); |
||
298 |
ParsePath("/etc/cvmfs/default.local", false); |
||
299 |
|||
300 |
if (fqrn != "") { |
||
301 |
string domain; |
||
302 |
vector<string> tokens = SplitString(fqrn, '.'); |
||
303 |
assert(tokens.size() > 1); |
||
304 |
tokens.erase(tokens.begin()); |
||
305 |
domain = JoinStrings(tokens, "."); |
||
306 |
|||
307 |
if (HasConfigRepository(fqrn, &external_config_path)) |
||
308 |
ParsePath(external_config_path+ "domain.d/" + domain + ".conf", |
||
309 |
true); |
||
310 |
ParsePath("/etc/cvmfs/domain.d/" + domain + ".conf", false); |
||
311 |
ParsePath("/etc/cvmfs/domain.d/" + domain + ".local", false); |
||
312 |
|||
313 |
if (HasConfigRepository(fqrn, &external_config_path)) |
||
314 |
ParsePath(external_config_path + "config.d/" + fqrn + ".conf", true); |
||
315 |
ParsePath("/etc/cvmfs/config.d/" + fqrn + ".conf", false); |
||
316 |
ParsePath("/etc/cvmfs/config.d/" + fqrn + ".local", false); |
||
317 |
} |
||
318 |
} |
||
319 |
|||
320 |
|||
321 |
1620 |
void OptionsManager::PopulateParameter( |
|
322 |
const string ¶m, |
||
323 |
ConfigValue val) { |
||
324 |
1620 |
map<string, string>::const_iterator iter = protected_parameters_.find(param); |
|
325 |
✓✓✓✗ ✓✓ |
1620 |
if ((iter != protected_parameters_.end()) && (iter->second != val.value)) { |
326 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, |
||
327 |
"error in cvmfs configuration: attempt to change protected %s " |
||
328 |
"from %s to %s", |
||
329 |
2 |
param.c_str(), iter->second.c_str(), val.value.c_str()); |
|
330 |
2 |
return; |
|
331 |
} |
||
332 |
1618 |
ParseValue(param, &val); |
|
333 |
1618 |
config_[param] = val; |
|
334 |
1618 |
UpdateEnvironment(param, val); |
|
335 |
} |
||
336 |
|||
337 |
1622 |
void OptionsManager::UpdateEnvironment( |
|
338 |
const string ¶m, |
||
339 |
ConfigValue val) { |
||
340 |
✓✓ | 1622 |
if (taint_environment_) { |
341 |
1510 |
int retval = setenv(param.c_str(), val.value.c_str(), 1); |
|
342 |
✗✓ | 1510 |
assert(retval == 0); |
343 |
} |
||
344 |
1622 |
} |
|
345 |
|||
346 |
1618 |
void OptionsManager::ParseValue(std::string param, ConfigValue *val) { |
|
347 |
1618 |
string orig = val->value; |
|
348 |
1618 |
bool has_templ = opt_templ_mgr_->ParseString(&(val->value)); |
|
349 |
✓✓ | 1618 |
if (has_templ) { |
350 |
14 |
templatable_values_[param] = orig; |
|
351 |
} |
||
352 |
1618 |
} |
|
353 |
|||
354 |
|||
355 |
2 |
void OptionsManager::ProtectParameter(const string ¶m) { |
|
356 |
2 |
string value; |
|
357 |
// We don't care about the result. If param does not yet exists, we lock it |
||
358 |
// to the empty string. |
||
359 |
2 |
(void) GetValue(param, &value); |
|
360 |
2 |
protected_parameters_[param] = value; |
|
361 |
2 |
} |
|
362 |
|||
363 |
|||
364 |
2 |
void OptionsManager::ClearConfig() { |
|
365 |
2 |
config_.clear(); |
|
366 |
2 |
} |
|
367 |
|||
368 |
|||
369 |
694 |
bool OptionsManager::IsDefined(const std::string &key) { |
|
370 |
694 |
map<string, ConfigValue>::const_iterator iter = config_.find(key); |
|
371 |
694 |
return iter != config_.end(); |
|
372 |
} |
||
373 |
|||
374 |
|||
375 |
7656 |
bool OptionsManager::GetValue(const string &key, string *value) { |
|
376 |
7656 |
map<string, ConfigValue>::const_iterator iter = config_.find(key); |
|
377 |
✓✓ | 7656 |
if (iter != config_.end()) { |
378 |
2751 |
*value = iter->second.value; |
|
379 |
2751 |
return true; |
|
380 |
} |
||
381 |
4905 |
*value = ""; |
|
382 |
4905 |
return false; |
|
383 |
} |
||
384 |
|||
385 |
|||
386 |
946 |
bool OptionsManager::GetSource(const string &key, string *value) { |
|
387 |
946 |
map<string, ConfigValue>::const_iterator iter = config_.find(key); |
|
388 |
✓✗ | 946 |
if (iter != config_.end()) { |
389 |
946 |
*value = iter->second.source; |
|
390 |
946 |
return true; |
|
391 |
} |
||
392 |
*value = ""; |
||
393 |
return false; |
||
394 |
} |
||
395 |
|||
396 |
|||
397 |
183 |
bool OptionsManager::IsOn(const std::string ¶m_value) { |
|
398 |
183 |
const string uppercase = ToUpper(param_value); |
|
399 |
return ((uppercase == "YES") || (uppercase == "ON") || (uppercase == "1") || |
||
400 |
✓✓✓✗ ✓✗✗✓ |
183 |
(uppercase == "TRUE")); |
401 |
} |
||
402 |
|||
403 |
|||
404 |
141 |
vector<string> OptionsManager::GetAllKeys() { |
|
405 |
141 |
vector<string> result; |
|
406 |
✓✓ | 1244 |
for (map<string, ConfigValue>::const_iterator i = config_.begin(), |
407 |
141 |
iEnd = config_.end(); i != iEnd; ++i) |
|
408 |
{ |
||
409 |
962 |
result.push_back(i->first); |
|
410 |
} |
||
411 |
141 |
return result; |
|
412 |
} |
||
413 |
|||
414 |
|||
415 |
68 |
vector<string> OptionsManager::GetEnvironmentSubset( |
|
416 |
const string &key_prefix, |
||
417 |
bool strip_prefix) |
||
418 |
{ |
||
419 |
68 |
vector<string> result; |
|
420 |
✓✓ | 248 |
for (map<string, ConfigValue>::const_iterator i = config_.begin(), |
421 |
68 |
iEnd = config_.end(); i != iEnd; ++i) |
|
422 |
{ |
||
423 |
112 |
const bool ignore_prefix = false; |
|
424 |
✓✓ | 112 |
if (HasPrefix(i->first, key_prefix, ignore_prefix)) { |
425 |
const string output_key = strip_prefix |
||
426 |
? i->first.substr(key_prefix.length()) |
||
427 |
✓✓ | 14 |
: i->first; |
428 |
14 |
result.push_back(output_key + "=" + i->second.value); |
|
429 |
} |
||
430 |
} |
||
431 |
68 |
return result; |
|
432 |
} |
||
433 |
|||
434 |
|||
435 |
137 |
string OptionsManager::Dump() { |
|
436 |
137 |
string result; |
|
437 |
137 |
vector<string> keys = GetAllKeys(); |
|
438 |
✗✗✓✓ |
137 |
for (unsigned i = 0, l = keys.size(); i < l; ++i) { |
439 |
bool retval; |
||
440 |
934 |
string value; |
|
441 |
934 |
string source; |
|
442 |
|||
443 |
934 |
retval = GetValue(keys[i], &value); |
|
444 |
✗✓ | 934 |
assert(retval); |
445 |
934 |
retval = GetSource(keys[i], &source); |
|
446 |
✗✓ | 934 |
assert(retval); |
447 |
result += keys[i] + "=" + EscapeShell(value) + |
||
448 |
934 |
" # from " + source + "\n"; |
|
449 |
} |
||
450 |
return result; |
||
451 |
} |
||
452 |
|||
453 |
|||
454 |
557 |
void OptionsManager::SetValue(const string &key, const string &value) { |
|
455 |
557 |
ConfigValue config_value; |
|
456 |
557 |
config_value.source = "@INTERNAL@"; |
|
457 |
557 |
config_value.value = value; |
|
458 |
557 |
PopulateParameter(key, config_value); |
|
459 |
557 |
} |
|
460 |
|||
461 |
|||
462 |
35 |
void OptionsManager::UnsetValue(const string &key) { |
|
463 |
35 |
protected_parameters_.erase(key); |
|
464 |
35 |
config_.erase(key); |
|
465 |
✓✓ | 35 |
if (taint_environment_) |
466 |
33 |
unsetenv(key.c_str()); |
|
467 |
35 |
} |
|
468 |
|||
469 |
const char *DefaultOptionsTemplateManager |
||
470 |
::kTemplateIdentFqrn = "fqrn"; |
||
471 |
|||
472 |
const char *DefaultOptionsTemplateManager |
||
473 |
::kTemplateIdentOrg = "org"; |
||
474 |
|||
475 |
113 |
DefaultOptionsTemplateManager::DefaultOptionsTemplateManager( |
|
476 |
113 |
std::string fqrn) { |
|
477 |
113 |
SetTemplate(kTemplateIdentFqrn, fqrn); |
|
478 |
113 |
vector<string> fqrn_parts = SplitString(fqrn, '.'); |
|
479 |
113 |
SetTemplate(kTemplateIdentOrg, fqrn_parts[0]); |
|
480 |
} |
||
481 |
|||
482 |
244 |
void OptionsTemplateManager::SetTemplate(std::string name, std::string val) { |
|
483 |
244 |
templates_[name] = val; |
|
484 |
244 |
} |
|
485 |
|||
486 |
94 |
std::string OptionsTemplateManager::GetTemplate(std::string name) { |
|
487 |
✓✓ | 94 |
if (templates_.count(name)) { |
488 |
38 |
return templates_[name]; |
|
489 |
} else { |
||
490 |
56 |
std::string var_name = "@" + name + "@"; |
|
491 |
LogCvmfs(kLogCvmfs, kLogDebug, "Undeclared variable: %s", |
||
492 |
56 |
var_name.c_str()); |
|
493 |
56 |
return var_name; |
|
494 |
} |
||
495 |
} |
||
496 |
|||
497 |
1638 |
bool OptionsTemplateManager::ParseString(std::string *input) { |
|
498 |
1638 |
std::string result; |
|
499 |
1638 |
std::string in = *input; |
|
500 |
1638 |
bool has_vars = false; |
|
501 |
1638 |
int mode = 0; |
|
502 |
1638 |
std::string stock; |
|
503 |
✓✓ | 77112 |
for (std::string::size_type i = 0; i < in.size(); i++) { |
504 |
✓✓✗ | 75474 |
switch (mode) { |
505 |
case 0: |
||
506 |
✓✓ | 75078 |
if (in[i] == '@') { |
507 |
86 |
mode = 1; |
|
508 |
} else { |
||
509 |
74992 |
result += in[i]; |
|
510 |
} |
||
511 |
75078 |
break; |
|
512 |
case 1: |
||
513 |
✓✓ | 396 |
if (in[i] == '@') { |
514 |
66 |
mode = 0; |
|
515 |
66 |
result += GetTemplate(stock); |
|
516 |
66 |
stock = ""; |
|
517 |
66 |
has_vars = true; |
|
518 |
} else { |
||
519 |
330 |
stock += in[i]; |
|
520 |
} |
||
521 |
break; |
||
522 |
} |
||
523 |
} |
||
524 |
✓✓ | 1638 |
if (mode == 1) { |
525 |
20 |
result += "@" + stock; |
|
526 |
} |
||
527 |
1638 |
*input = result; |
|
528 |
1638 |
return has_vars; |
|
529 |
} |
||
530 |
|||
531 |
28 |
bool OptionsTemplateManager::HasTemplate(std::string name) { |
|
532 |
28 |
return templates_.count(name); |
|
533 |
} |
||
534 |
|||
535 |
#ifdef CVMFS_NAMESPACE_GUARD |
||
536 |
} // namespace CVMFS_NAMESPACE_GUARD |
||
537 |
#endif |
Generated by: GCOVR (Version 4.1) |