GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/options.cc
Date: 2025-08-31 02:39:21
Exec Total Coverage
Lines: 274 354 77.4%
Branches: 280 655 42.7%

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
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 "sanitizer.h"
22 #include "util/exception.h"
23 #include "util/logging.h"
24 #include "util/posix.h"
25 #include "util/string.h"
26
27 using namespace std; // NOLINT
28
29 #ifdef CVMFS_NAMESPACE_GUARD
30 namespace CVMFS_NAMESPACE_GUARD {
31 #endif
32
33
34 5170 static string EscapeShell(const std::string &raw) {
35
2/2
✓ Branch 1 taken 103916 times.
✓ Branch 2 taken 5127 times.
109043 for (unsigned i = 0, l = raw.length(); i < l; ++i) {
36
6/6
✓ Branch 1 taken 92715 times.
✓ Branch 2 taken 11201 times.
✓ Branch 4 taken 79020 times.
✓ Branch 5 taken 13695 times.
✓ Branch 6 taken 43 times.
✓ Branch 7 taken 103873 times.
194137 if (!(((raw[i] >= '0') && (raw[i] <= '9'))
37
4/4
✓ Branch 1 taken 78619 times.
✓ Branch 2 taken 11602 times.
✓ Branch 4 taken 72270 times.
✓ Branch 5 taken 6349 times.
90221 || ((raw[i] >= 'A') && (raw[i] <= 'Z'))
38
5/6
✓ Branch 1 taken 67544 times.
✓ Branch 2 taken 16328 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 67544 times.
✓ Branch 7 taken 8658 times.
✓ Branch 8 taken 7670 times.
83872 || ((raw[i] >= 'a') && (raw[i] <= 'z')) || (raw[i] == '/')
39
6/6
✓ Branch 1 taken 8297 times.
✓ Branch 2 taken 361 times.
✓ Branch 4 taken 4793 times.
✓ Branch 5 taken 3504 times.
✓ Branch 7 taken 67 times.
✓ Branch 8 taken 4726 times.
8658 || (raw[i] == ':') || (raw[i] == '.') || (raw[i] == '_')
40
3/4
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 24 times.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
67 || (raw[i] == '-') || (raw[i] == ','))) {
41 43 goto escape_shell_quote;
42 }
43 }
44
1/2
✓ Branch 1 taken 5127 times.
✗ Branch 2 not taken.
5127 return raw;
45
46 43 escape_shell_quote:
47
1/2
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
86 string result = "'";
48
2/2
✓ Branch 1 taken 704 times.
✓ Branch 2 taken 43 times.
747 for (unsigned i = 0, l = raw.length(); i < l; ++i) {
49
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 704 times.
704 if (raw[i] == '\'')
50 result += "\\";
51
1/2
✓ Branch 2 taken 704 times.
✗ Branch 3 not taken.
704 result += raw[i];
52 }
53
1/2
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
43 result += "'";
54 43 return result;
55 }
56
57
58 5822 string OptionsManager::TrimParameter(const string &parameter) {
59 5822 string result = Trim(parameter);
60 // Strip "readonly"
61
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5822 times.
5822 if (result.find("readonly ") == 0) {
62 result = result.substr(9);
63 result = Trim(result);
64
2/2
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 5492 times.
5822 } else if (result.find("export ") == 0) {
65
1/2
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
330 result = result.substr(7);
66
1/2
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
330 result = Trim(result);
67
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5492 times.
5492 } else if (result.find("eval ") == 0) {
68 result = result.substr(5);
69 result = Trim(result);
70 }
71 5822 return result;
72 }
73
74 6812 string OptionsManager::SanitizeParameterAssignment(string *line,
75 vector<string> *tokens) {
76 6812 const size_t comment_idx = line->find("#");
77
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 6152 times.
6812 if (comment_idx != string::npos)
78
1/2
✓ Branch 1 taken 660 times.
✗ Branch 2 not taken.
660 *line = line->substr(0, comment_idx);
79
1/2
✓ Branch 1 taken 6812 times.
✗ Branch 2 not taken.
6812 *line = Trim(*line);
80
2/2
✓ Branch 1 taken 660 times.
✓ Branch 2 taken 6152 times.
6812 if (line->empty())
81
1/2
✓ Branch 2 taken 660 times.
✗ Branch 3 not taken.
660 return "";
82
1/2
✓ Branch 1 taken 6152 times.
✗ Branch 2 not taken.
6152 *tokens = SplitString(*line, '=');
83
2/2
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 5822 times.
6152 if (tokens->size() < 2)
84
1/2
✓ Branch 2 taken 330 times.
✗ Branch 3 not taken.
330 return "";
85
1/2
✓ Branch 2 taken 5822 times.
✗ Branch 3 not taken.
5822 string parameter = TrimParameter((*tokens)[0]);
86
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5822 times.
5822 if (parameter.find(" ") != string::npos)
87 return "";
88 5822 return parameter;
89 5822 }
90
91 352 void OptionsManager::SwitchTemplateManager(
92 OptionsTemplateManager *opt_templ_mgr_param) {
93
1/2
✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
352 delete opt_templ_mgr_;
94
1/2
✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
352 if (opt_templ_mgr_param != NULL) {
95 352 opt_templ_mgr_ = opt_templ_mgr_param;
96 } else {
97 opt_templ_mgr_ = new OptionsTemplateManager();
98 }
99 352 for (std::map<std::string, std::string>::iterator it =
100 352 templatable_values_.begin();
101
2/2
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 352 times.
481 it != templatable_values_.end();
102 129 it++) {
103
2/4
✓ Branch 3 taken 129 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 129 times.
✗ Branch 7 not taken.
129 config_[it->first].value = it->second;
104
2/4
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 129 times.
✗ Branch 6 not taken.
129 opt_templ_mgr_->ParseString(&(config_[it->first].value));
105
2/4
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 129 times.
✗ Branch 6 not taken.
129 UpdateEnvironment(it->first, config_[it->first]);
106 }
107 352 }
108
109 387 bool SimpleOptionsParser::TryParsePath(const string &config_file) {
110
1/2
✓ Branch 2 taken 387 times.
✗ Branch 3 not taken.
387 LogCvmfs(kLogCvmfs, kLogDebug, "Fast-parsing config file %s",
111 config_file.c_str());
112 387 string line;
113
1/2
✓ Branch 2 taken 387 times.
✗ Branch 3 not taken.
387 FILE *fconfig = fopen(config_file.c_str(), "r");
114
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 344 times.
387 if (fconfig == NULL)
115 43 return false;
116
117 // Read line by line and extract parameters
118
3/4
✓ Branch 1 taken 5332 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4988 times.
✓ Branch 4 taken 344 times.
5332 while (GetLineFile(fconfig, &line)) {
119 4988 vector<string> tokens;
120
1/2
✓ Branch 1 taken 4988 times.
✗ Branch 2 not taken.
4988 const string parameter = SanitizeParameterAssignment(&line, &tokens);
121
2/2
✓ Branch 1 taken 1290 times.
✓ Branch 2 taken 3698 times.
4988 if (parameter.empty())
122 1290 continue;
123
124 // Strip quotes from value
125
1/2
✓ Branch 3 taken 3698 times.
✗ Branch 4 not taken.
3698 tokens.erase(tokens.begin());
126
3/6
✓ Branch 2 taken 3698 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3698 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3698 times.
✗ Branch 9 not taken.
7396 string value = Trim(JoinStrings(tokens, "="));
127 3698 const unsigned value_length = value.length();
128
2/2
✓ Branch 0 taken 2666 times.
✓ Branch 1 taken 1032 times.
3698 if (value_length > 2) {
129
3/7
✓ Branch 1 taken 2666 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 258 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 258 times.
2924 if (((value[0] == '"') && ((value[value_length - 1] == '"')))
130
9/13
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 2408 times.
✓ Branch 3 taken 2408 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 258 times.
✓ Branch 6 taken 2150 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 258 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 258 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 516 times.
✓ Branch 13 taken 2150 times.
2924 || ((value[0] == '\'') && ((value[value_length - 1] == '\'')))) {
131
1/2
✓ Branch 1 taken 516 times.
✗ Branch 2 not taken.
516 value = value.substr(1, value_length - 2);
132 }
133 }
134
135 3698 ConfigValue config_value;
136
1/2
✓ Branch 1 taken 3698 times.
✗ Branch 2 not taken.
3698 config_value.source = config_file;
137
1/2
✓ Branch 1 taken 3698 times.
✗ Branch 2 not taken.
3698 config_value.value = value;
138
2/4
✓ Branch 1 taken 3698 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3698 times.
✗ Branch 5 not taken.
3698 PopulateParameter(parameter, config_value);
139
4/4
✓ Branch 3 taken 3698 times.
✓ Branch 4 taken 1290 times.
✓ Branch 6 taken 3698 times.
✓ Branch 7 taken 1290 times.
6278 }
140
1/2
✓ Branch 1 taken 344 times.
✗ Branch 2 not taken.
344 fclose(fconfig);
141 344 return true;
142 387 }
143
144 156 void BashOptionsManager::ParsePath(const string &config_file,
145 const bool external) {
146
1/2
✓ Branch 2 taken 156 times.
✗ Branch 3 not taken.
156 LogCvmfs(kLogCvmfs, kLogDebug, "Parsing config file %s", config_file.c_str());
147 int retval;
148 int pipe_open[2];
149 int pipe_quit[2];
150 156 pid_t pid_child = 0;
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
156 if (external) {
152 // cvmfs can run in the process group of automount in which case
153 // autofs won't mount an additional config repository. We create a
154 // short-lived process that detaches from the process group and triggers
155 // autofs to mount the config repository, if necessary. It holds a file
156 // handle to the config file until the main process opened the file, too.
157 MakePipe(pipe_open);
158 MakePipe(pipe_quit);
159 switch (pid_child = fork()) {
160 case -1:
161 PANIC(NULL);
162 case 0: { // Child
163 close(pipe_open[0]);
164 close(pipe_quit[1]);
165 // If this is not a process group leader, create a new session
166 if (getpgrp() != getpid()) {
167 const pid_t new_session = setsid();
168 assert(new_session != (pid_t)-1);
169 }
170 (void)open(config_file.c_str(), O_RDONLY);
171 char ready = 'R';
172 WritePipe(pipe_open[1], &ready, 1);
173 retval = read(pipe_quit[0], &ready, 1);
174 _exit(retval); // Don't flush shared file descriptors
175 }
176 }
177 // Parent
178 close(pipe_open[1]);
179 close(pipe_quit[0]);
180 char ready = 0;
181 ReadPipe(pipe_open[0], &ready, 1);
182 assert(ready == 'R');
183 close(pipe_open[0]);
184 }
185
1/2
✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
156 const string config_path = GetParentPath(config_file);
186
1/2
✓ Branch 2 taken 156 times.
✗ Branch 3 not taken.
156 FILE *fconfig = fopen(config_file.c_str(), "r");
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
156 if (pid_child > 0) {
188 char c = 'C';
189 WritePipe(pipe_quit[1], &c, 1);
190 int statloc;
191 waitpid(pid_child, &statloc, 0);
192 close(pipe_quit[1]);
193 }
194
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 144 times.
156 if (!fconfig) {
195
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
12 if (external && !DirectoryExists(config_path)) {
196 string repo_required;
197 if (GetValue("CVMFS_CONFIG_REPO_REQUIRED", &repo_required)
198 && IsOn(repo_required)) {
199 LogCvmfs(
200 kLogCvmfs, kLogStderr | kLogSyslogErr,
201 "required configuration repository directory does not exist: %s",
202 config_path.c_str());
203 // Do not crash as in abort(), which can trigger core file creation
204 // from the mount helper
205 exit(1);
206 }
207
208 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogWarn,
209 "configuration repository directory does not exist: %s",
210 config_path.c_str());
211 }
212 12 return;
213 }
214
215 int fd_stdin;
216 int fd_stdout;
217 int fd_stderr;
218
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 retval = Shell(&fd_stdin, &fd_stdout, &fd_stderr);
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 assert(retval);
220
221 // Let the shell read the file
222 288 string line;
223
1/2
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
288 const string newline = "\n";
224
5/15
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 144 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 144 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 144 times.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 144 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
288 const string cd = "cd \"" + ((config_path == "") ? "/" : config_path) + "\""
225
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
288 + newline;
226
1/2
✓ Branch 3 taken 144 times.
✗ Branch 4 not taken.
144 WritePipe(fd_stdin, cd.data(), cd.length());
227
3/4
✓ Branch 1 taken 1968 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1824 times.
✓ Branch 4 taken 144 times.
1968 while (GetLineFile(fconfig, &line)) {
228
1/2
✓ Branch 3 taken 1824 times.
✗ Branch 4 not taken.
1824 WritePipe(fd_stdin, line.data(), line.length());
229
1/2
✓ Branch 3 taken 1824 times.
✗ Branch 4 not taken.
1824 WritePipe(fd_stdin, newline.data(), newline.length());
230 }
231
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 rewind(fconfig);
232
233 // Read line by line and extract parameters
234
3/4
✓ Branch 1 taken 1968 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1824 times.
✓ Branch 4 taken 144 times.
1968 while (GetLineFile(fconfig, &line)) {
235 1824 vector<string> tokens;
236
1/2
✓ Branch 1 taken 1824 times.
✗ Branch 2 not taken.
1824 const string parameter = SanitizeParameterAssignment(&line, &tokens);
237
2/2
✓ Branch 1 taken 360 times.
✓ Branch 2 taken 1464 times.
1824 if (parameter.empty())
238 360 continue;
239
240 1464 ConfigValue value;
241
1/2
✓ Branch 1 taken 1464 times.
✗ Branch 2 not taken.
1464 value.source = config_file;
242
2/4
✓ Branch 1 taken 1464 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1464 times.
✗ Branch 5 not taken.
1464 const string sh_echo = "echo $" + parameter + "\n";
243
1/2
✓ Branch 3 taken 1464 times.
✗ Branch 4 not taken.
1464 WritePipe(fd_stdin, sh_echo.data(), sh_echo.length());
244
1/2
✓ Branch 1 taken 1464 times.
✗ Branch 2 not taken.
1464 GetLineFd(fd_stdout, &value.value);
245
2/4
✓ Branch 1 taken 1464 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1464 times.
✗ Branch 5 not taken.
1464 PopulateParameter(parameter, value);
246
4/4
✓ Branch 3 taken 1464 times.
✓ Branch 4 taken 360 times.
✓ Branch 6 taken 1464 times.
✓ Branch 7 taken 360 times.
2184 }
247
248
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 close(fd_stderr);
249
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 close(fd_stdout);
250
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 close(fd_stdin);
251
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 fclose(fconfig);
252 }
253
254
255 486 bool OptionsManager::HasConfigRepository(const string &fqrn,
256 string *config_path) {
257 486 string cvmfs_mount_dir;
258
3/6
✓ Branch 2 taken 486 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 486 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 486 times.
486 if (!GetValue("CVMFS_MOUNT_DIR", &cvmfs_mount_dir)) {
259 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "CVMFS_MOUNT_DIR missing");
260 return false;
261 }
262
263 486 string config_repository;
264
4/6
✓ Branch 2 taken 486 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 486 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 477 times.
486 if (GetValue("CVMFS_CONFIG_REPOSITORY", &config_repository)) {
265
3/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
9 if (config_repository.empty() || (config_repository == fqrn))
266 return false;
267
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const sanitizer::RepositorySanitizer repository_sanitizer;
268
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
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
3/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
9 *config_path = cvmfs_mount_dir + "/" + config_repository + "/etc/cvmfs/";
275 9 return true;
276 9 }
277 477 return false;
278 486 }
279
280
281 void OptionsManager::ParseDefault(const string &fqrn) {
282 if (taint_environment_) {
283 const 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 = FindFilesBySuffix("/etc/cvmfs/default.d",
290 ".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", true);
309 ParsePath("/etc/cvmfs/domain.d/" + domain + ".conf", false);
310 ParsePath("/etc/cvmfs/domain.d/" + domain + ".local", false);
311
312 if (HasConfigRepository(fqrn, &external_config_path))
313 ParsePath(external_config_path + "config.d/" + fqrn + ".conf", true);
314 ParsePath("/etc/cvmfs/config.d/" + fqrn + ".conf", false);
315 ParsePath("/etc/cvmfs/config.d/" + fqrn + ".local", false);
316 }
317 }
318
319
320 12725 void OptionsManager::PopulateParameter(const string &param, ConfigValue val) {
321
1/2
✓ Branch 1 taken 12725 times.
✗ Branch 2 not taken.
12725 const map<string, string>::const_iterator iter = protected_parameters_.find(
322 12725 param);
323
5/6
✓ Branch 3 taken 55 times.
✓ Branch 4 taken 12670 times.
✓ Branch 7 taken 55 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 55 times.
✓ Branch 10 taken 12670 times.
12725 if ((iter != protected_parameters_.end()) && (iter->second != val.value)) {
324
1/3
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
110 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
325 "error in cvmfs configuration: attempt to change protected %s "
326 "from %s to %s",
327 55 param.c_str(), iter->second.c_str(), val.value.c_str());
328 55 return;
329 }
330
2/4
✓ Branch 1 taken 12670 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12670 times.
✗ Branch 5 not taken.
12670 ParseValue(param, &val);
331
2/4
✓ Branch 1 taken 12670 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12670 times.
✗ Branch 5 not taken.
12670 config_[param] = val;
332
1/2
✓ Branch 1 taken 12670 times.
✗ Branch 2 not taken.
12670 UpdateEnvironment(param, val);
333 }
334
335 12799 void OptionsManager::UpdateEnvironment(const string &param, ConfigValue val) {
336
2/2
✓ Branch 0 taken 8954 times.
✓ Branch 1 taken 3845 times.
12799 if (taint_environment_) {
337 8954 const int retval = setenv(param.c_str(), val.value.c_str(), 1);
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8954 times.
8954 assert(retval == 0);
339 }
340 12799 }
341
342 12670 void OptionsManager::ParseValue(std::string param, ConfigValue *val) {
343
1/2
✓ Branch 1 taken 12670 times.
✗ Branch 2 not taken.
12670 const string orig = val->value;
344
1/2
✓ Branch 1 taken 12670 times.
✗ Branch 2 not taken.
12670 const bool has_templ = opt_templ_mgr_->ParseString(&(val->value));
345
2/2
✓ Branch 0 taken 404 times.
✓ Branch 1 taken 12266 times.
12670 if (has_templ) {
346
2/4
✓ Branch 1 taken 404 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 404 times.
✗ Branch 5 not taken.
404 templatable_values_[param] = orig;
347 }
348 12670 }
349
350
351 55 void OptionsManager::ProtectParameter(const string &param) {
352 55 string value;
353 // We don't care about the result. If param does not yet exists, we lock it
354 // to the empty string.
355
1/2
✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
55 (void)GetValue(param, &value);
356
2/4
✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
55 protected_parameters_[param] = value;
357 55 }
358
359
360 55 void OptionsManager::ClearConfig() { config_.clear(); }
361
362
363 6292 bool OptionsManager::IsDefined(const std::string &key) {
364
1/2
✓ Branch 1 taken 6292 times.
✗ Branch 2 not taken.
6292 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
365 6292 return iter != config_.end();
366 }
367
368
369 61839 bool OptionsManager::GetValue(const string &key, string *value) const {
370
1/2
✓ Branch 1 taken 61839 times.
✗ Branch 2 not taken.
61839 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
371
2/2
✓ Branch 2 taken 13740 times.
✓ Branch 3 taken 48099 times.
61839 if (iter != config_.end()) {
372
1/2
✓ Branch 2 taken 13740 times.
✗ Branch 3 not taken.
13740 *value = iter->second.value;
373 13740 return true;
374 }
375
1/2
✓ Branch 1 taken 48099 times.
✗ Branch 2 not taken.
48099 *value = "";
376 48099 return false;
377 }
378
379
380 108 std::string OptionsManager::GetValueOrDie(const string &key) {
381 108 std::string value;
382
1/2
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
108 const bool retval = GetValue(key, &value);
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!retval) {
384 PANIC(kLogStderr | kLogDebug, "%s configuration parameter missing",
385 key.c_str());
386 }
387 108 return value;
388 }
389
390
391 5500 bool OptionsManager::GetSource(const string &key, string *value) {
392
1/2
✓ Branch 1 taken 5500 times.
✗ Branch 2 not taken.
5500 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
393
1/2
✓ Branch 3 taken 5500 times.
✗ Branch 4 not taken.
5500 if (iter != config_.end()) {
394
1/2
✓ Branch 2 taken 5500 times.
✗ Branch 3 not taken.
5500 *value = iter->second.source;
395 5500 return true;
396 }
397 *value = "";
398 return false;
399 }
400
401
402 459 bool OptionsManager::IsOn(const std::string &param_value) const {
403
1/2
✓ Branch 1 taken 459 times.
✗ Branch 2 not taken.
459 const string uppercase = ToUpper(param_value);
404
2/4
✓ Branch 2 taken 435 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 435 times.
✗ Branch 6 not taken.
894 return ((uppercase == "YES") || (uppercase == "ON") || (uppercase == "1")
405
3/4
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 435 times.
1353 || (uppercase == "TRUE"));
406 459 }
407
408
409 86 bool OptionsManager::IsOff(const std::string &param_value) const {
410
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
86 const string uppercase = ToUpper(param_value);
411
3/4
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 43 times.
✓ Branch 5 taken 43 times.
✗ Branch 6 not taken.
172 return ((uppercase == "NO") || (uppercase == "OFF") || (uppercase == "0")
412
2/4
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
258 || (uppercase == "FALSE"));
413 86 }
414
415
416 1074 vector<string> OptionsManager::GetAllKeys() {
417 1074 vector<string> result;
418 1074 for (map<string, ConfigValue>::const_iterator i = config_.begin(),
419 1074 iEnd = config_.end();
420
2/2
✓ Branch 1 taken 5940 times.
✓ Branch 2 taken 1074 times.
7014 i != iEnd;
421 5940 ++i) {
422
1/2
✓ Branch 2 taken 5940 times.
✗ Branch 3 not taken.
5940 result.push_back(i->first);
423 }
424 1074 return result;
425 }
426
427
428 236 vector<string> OptionsManager::GetEnvironmentSubset(const string &key_prefix,
429 bool strip_prefix) {
430 236 vector<string> result;
431 236 for (map<string, ConfigValue>::const_iterator i = config_.begin(),
432 236 iEnd = config_.end();
433
2/2
✓ Branch 1 taken 3080 times.
✓ Branch 2 taken 236 times.
3316 i != iEnd;
434 3080 ++i) {
435 3080 const bool ignore_prefix = false;
436
3/4
✓ Branch 2 taken 3080 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 385 times.
✓ Branch 5 taken 2695 times.
3080 if (HasPrefix(i->first, key_prefix, ignore_prefix)) {
437 const string output_key = strip_prefix
438 55 ? i->first.substr(key_prefix.length())
439
4/6
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 330 times.
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 330 times.
✗ Branch 9 not taken.
440 : i->first;
440
3/6
✓ Branch 2 taken 385 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 385 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 385 times.
✗ Branch 9 not taken.
385 result.push_back(output_key + "=" + i->second.value);
441 385 }
442 }
443 236 return result;
444 }
445
446
447 964 string OptionsManager::Dump() {
448 964 string result;
449
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
964 vector<string> keys = GetAllKeys();
450
2/2
✓ Branch 1 taken 5170 times.
✓ Branch 2 taken 964 times.
6134 for (unsigned i = 0, l = keys.size(); i < l; ++i) {
451 bool retval;
452 5170 string value;
453 5170 string source;
454
455
1/2
✓ Branch 2 taken 5170 times.
✗ Branch 3 not taken.
5170 retval = GetValue(keys[i], &value);
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5170 times.
5170 assert(retval);
457
1/2
✓ Branch 2 taken 5170 times.
✗ Branch 3 not taken.
5170 retval = GetSource(keys[i], &source);
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5170 times.
5170 assert(retval);
459
5/10
✓ Branch 1 taken 5170 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5170 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5170 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 5170 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 5170 times.
✗ Branch 15 not taken.
10340 result += keys[i] + "=" + EscapeShell(value) + " # from " + source
460
2/4
✓ Branch 1 taken 5170 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5170 times.
✗ Branch 5 not taken.
5170 + "\n";
461 5170 }
462 1928 return result;
463 964 }
464
465 void OptionsManager::SetValueFromTalk(const string &key, const string &value) {
466 ConfigValue config_value;
467 config_value.source = "cvmfs_talk";
468 config_value.value = value;
469 PopulateParameter(key, config_value);
470 }
471
472 7563 void OptionsManager::SetValue(const string &key, const string &value) {
473 7563 ConfigValue config_value;
474
1/2
✓ Branch 1 taken 7563 times.
✗ Branch 2 not taken.
7563 config_value.source = "@INTERNAL@";
475
1/2
✓ Branch 1 taken 7563 times.
✗ Branch 2 not taken.
7563 config_value.value = value;
476
2/4
✓ Branch 1 taken 7563 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7563 times.
✗ Branch 5 not taken.
7563 PopulateParameter(key, config_value);
477 7563 }
478
479
480 349 void OptionsManager::UnsetValue(const string &key) {
481 349 protected_parameters_.erase(key);
482 349 config_.erase(key);
483
2/2
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 55 times.
349 if (taint_environment_)
484 294 unsetenv(key.c_str());
485 349 }
486
487 const char *DefaultOptionsTemplateManager ::kTemplateIdentFqrn = "fqrn";
488
489 const char *DefaultOptionsTemplateManager ::kTemplateIdentOrg = "org";
490
491 403 DefaultOptionsTemplateManager::DefaultOptionsTemplateManager(std::string fqrn) {
492
3/6
✓ Branch 1 taken 403 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 403 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 403 times.
✗ Branch 9 not taken.
403 SetTemplate(kTemplateIdentFqrn, fqrn);
493
1/2
✓ Branch 1 taken 403 times.
✗ Branch 2 not taken.
403 vector<string> fqrn_parts = SplitString(fqrn, '.');
494
3/6
✓ Branch 2 taken 403 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 403 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 403 times.
✗ Branch 10 not taken.
403 SetTemplate(kTemplateIdentOrg, fqrn_parts[0]);
495 403 }
496
497 873 void OptionsTemplateManager::SetTemplate(std::string name, std::string val) {
498 873 templates_[name] = val;
499 873 }
500
501 1339 std::string OptionsTemplateManager::GetTemplate(std::string name) {
502
2/2
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 1131 times.
1339 if (templates_.count(name)) {
503 208 return templates_[name];
504 } else {
505
2/4
✓ Branch 1 taken 1131 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1131 times.
✗ Branch 5 not taken.
1131 std::string var_name = "@" + name + "@";
506
1/2
✓ Branch 2 taken 1131 times.
✗ Branch 3 not taken.
1131 LogCvmfs(kLogCvmfs, kLogDebug, "Undeclared variable: %s", var_name.c_str());
507 1131 return var_name;
508 1131 }
509 }
510
511 12811 bool OptionsTemplateManager::ParseString(std::string *input) {
512 12811 std::string result;
513
1/2
✓ Branch 1 taken 12811 times.
✗ Branch 2 not taken.
12811 std::string in = *input;
514 12811 bool has_vars = false;
515 12811 int mode = 0;
516 12811 std::string stock;
517
2/2
✓ Branch 1 taken 202997 times.
✓ Branch 2 taken 12811 times.
215808 for (std::string::size_type i = 0; i < in.size(); i++) {
518
2/3
✓ Branch 0 taken 194932 times.
✓ Branch 1 taken 8065 times.
✗ Branch 2 not taken.
202997 switch (mode) {
519 194932 case 0:
520
3/4
✓ Branch 1 taken 194932 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1654 times.
✓ Branch 4 taken 193278 times.
194932 if (in[i] == '@') {
521 1654 mode = 1;
522 } else {
523
2/4
✓ Branch 1 taken 193278 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 193278 times.
✗ Branch 5 not taken.
193278 result += in[i];
524 }
525 194932 break;
526 8065 case 1:
527
3/4
✓ Branch 1 taken 8065 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1318 times.
✓ Branch 4 taken 6747 times.
8065 if (in[i] == '@') {
528 1318 mode = 0;
529
3/6
✓ Branch 1 taken 1318 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1318 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1318 times.
✗ Branch 8 not taken.
1318 result += GetTemplate(stock);
530
1/2
✓ Branch 1 taken 1318 times.
✗ Branch 2 not taken.
1318 stock = "";
531 1318 has_vars = true;
532 } else {
533
2/4
✓ Branch 1 taken 6747 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6747 times.
✗ Branch 5 not taken.
6747 stock += in[i];
534 }
535 8065 break;
536 }
537 }
538
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 12475 times.
12811 if (mode == 1) {
539
2/4
✓ Branch 1 taken 336 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 336 times.
✗ Branch 5 not taken.
336 result += "@" + stock;
540 }
541
1/2
✓ Branch 1 taken 12811 times.
✗ Branch 2 not taken.
12811 *input = result;
542 12811 return has_vars;
543 12811 }
544
545 21 bool OptionsTemplateManager::HasTemplate(std::string name) {
546 21 return templates_.count(name);
547 }
548
549 #ifdef CVMFS_NAMESPACE_GUARD
550 } // namespace CVMFS_NAMESPACE_GUARD
551 #endif
552