GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/options.cc
Date: 2026-10-11 02:40:02
Exec Total Coverage
Lines: 274 361 75.9%
Branches: 280 675 41.5%

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 14293 static string EscapeShell(const std::string &raw) {
35
2/2
✓ Branch 1 taken 176347 times.
✓ Branch 2 taken 14216 times.
190563 for (unsigned i = 0, l = raw.length(); i < l; ++i) {
36
6/6
✓ Branch 1 taken 153986 times.
✓ Branch 2 taken 22361 times.
✓ Branch 4 taken 140562 times.
✓ Branch 5 taken 13424 times.
✓ Branch 6 taken 77 times.
✓ Branch 7 taken 176270 times.
339270 if (!(((raw[i] >= '0') && (raw[i] <= '9'))
37
4/4
✓ Branch 1 taken 140076 times.
✓ Branch 2 taken 22847 times.
✓ Branch 4 taken 125619 times.
✓ Branch 5 taken 14457 times.
162923 || ((raw[i] >= 'A') && (raw[i] <= 'Z'))
38
5/6
✓ Branch 1 taken 117037 times.
✓ Branch 2 taken 31429 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 117037 times.
✓ Branch 7 taken 16914 times.
✓ Branch 8 taken 14515 times.
148466 || ((raw[i] >= 'a') && (raw[i] <= 'z')) || (raw[i] == '/')
39
6/6
✓ Branch 1 taken 16468 times.
✓ Branch 2 taken 446 times.
✓ Branch 4 taken 8955 times.
✓ Branch 5 taken 7513 times.
✓ Branch 7 taken 373 times.
✓ Branch 8 taken 8582 times.
16914 || (raw[i] == ':') || (raw[i] == '.') || (raw[i] == '_')
40
3/4
✓ Branch 1 taken 77 times.
✓ Branch 2 taken 296 times.
✓ Branch 4 taken 77 times.
✗ Branch 5 not taken.
373 || (raw[i] == '-') || (raw[i] == ','))) {
41 77 goto escape_shell_quote;
42 }
43 }
44
1/2
✓ Branch 1 taken 14216 times.
✗ Branch 2 not taken.
14216 return raw;
45
46 77 escape_shell_quote:
47
1/2
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
154 string result = "'";
48
2/2
✓ Branch 1 taken 3696 times.
✓ Branch 2 taken 77 times.
3773 for (unsigned i = 0, l = raw.length(); i < l; ++i) {
49
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3696 times.
3696 if (raw[i] == '\'')
50 ✗ result += "\\";
51
1/2
✓ Branch 2 taken 3696 times.
✗ Branch 3 not taken.
3696 result += raw[i];
52 }
53
1/2
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
77 result += "'";
54 77 return result;
55 }
56
57
58 10048 string OptionsManager::TrimParameter(const string &parameter) {
59 10048 string result = Trim(parameter);
60 // Strip "readonly"
61
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10048 times.
10048 if (result.find("readonly ") == 0) {
62 ✗ result = result.substr(9);
63 ✗ result = Trim(result);
64
2/2
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 9748 times.
10048 } else if (result.find("export ") == 0) {
65
1/2
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
300 result = result.substr(7);
66
1/2
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
300 result = Trim(result);
67
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9748 times.
9748 } else if (result.find("eval ") == 0) {
68 ✗ result = result.substr(5);
69 ✗ result = Trim(result);
70 }
71 10048 return result;
72 }
73
74 10948 string OptionsManager::SanitizeParameterAssignment(string *line,
75 vector<string> *tokens) {
76 10948 const size_t comment_idx = line->find("#");
77
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 10348 times.
10948 if (comment_idx != string::npos)
78
1/2
✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
600 *line = line->substr(0, comment_idx);
79
1/2
✓ Branch 1 taken 10948 times.
✗ Branch 2 not taken.
10948 *line = Trim(*line);
80
2/2
✓ Branch 1 taken 600 times.
✓ Branch 2 taken 10348 times.
10948 if (line->empty())
81
1/2
✓ Branch 2 taken 600 times.
✗ Branch 3 not taken.
600 return "";
82
1/2
✓ Branch 1 taken 10348 times.
✗ Branch 2 not taken.
10348 *tokens = SplitString(*line, '=');
83
2/2
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 10048 times.
10348 if (tokens->size() < 2)
84
1/2
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
300 return "";
85
1/2
✓ Branch 2 taken 10048 times.
✗ Branch 3 not taken.
10048 string parameter = TrimParameter((*tokens)[0]);
86
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10048 times.
10048 if (parameter.find(" ") != string::npos)
87 ✗ return "";
88 10048 return parameter;
89 10048 }
90
91 75 void OptionsManager::SwitchTemplateManager(
92 OptionsTemplateManager *opt_templ_mgr_param) {
93
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 delete opt_templ_mgr_;
94
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 if (opt_templ_mgr_param != NULL) {
95 75 opt_templ_mgr_ = opt_templ_mgr_param;
96 } else {
97 ✗ opt_templ_mgr_ = new OptionsTemplateManager();
98 }
99 75 for (std::map<std::string, std::string>::iterator it =
100 75 templatable_values_.begin();
101
2/2
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 75 times.
131 it != templatable_values_.end();
102 56 it++) {
103
2/4
✓ Branch 3 taken 56 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 56 times.
✗ Branch 7 not taken.
56 config_[it->first].value = it->second;
104
2/4
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 56 times.
✗ Branch 6 not taken.
56 opt_templ_mgr_->ParseString(&(config_[it->first].value));
105
2/4
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 56 times.
✗ Branch 6 not taken.
56 UpdateEnvironment(it->first, config_[it->first]);
106 }
107 75 }
108
109 9 bool SimpleOptionsParser::TryParsePath(const string &config_file) {
110
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 LogCvmfs(kLogCvmfs, kLogDebug, "Fast-parsing config file %s",
111 config_file.c_str());
112 9 string line;
113
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 FILE *fconfig = fopen(config_file.c_str(), "r");
114
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (fconfig == NULL)
115 1 return false;
116
117 // Read line by line and extract parameters
118
3/4
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 116 times.
✓ Branch 4 taken 8 times.
124 while (GetLineFile(fconfig, &line)) {
119 116 vector<string> tokens;
120
1/2
✓ Branch 1 taken 116 times.
✗ Branch 2 not taken.
116 const string parameter = SanitizeParameterAssignment(&line, &tokens);
121
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 86 times.
116 if (parameter.empty())
122 30 continue;
123
124 // Strip quotes from value
125
1/2
✓ Branch 3 taken 86 times.
✗ Branch 4 not taken.
86 tokens.erase(tokens.begin());
126
3/6
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 86 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 86 times.
✗ Branch 9 not taken.
172 string value = Trim(JoinStrings(tokens, "="));
127 86 const unsigned value_length = value.length();
128
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 24 times.
86 if (value_length > 2) {
129
3/7
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
68 if (((value[0] == '"') && ((value[value_length - 1] == '"')))
130
9/13
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 56 times.
✓ Branch 3 taken 56 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 50 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12 times.
✓ Branch 13 taken 50 times.
68 || ((value[0] == '\'') && ((value[value_length - 1] == '\'')))) {
131
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 value = value.substr(1, value_length - 2);
132 }
133 }
134
135 86 ConfigValue config_value;
136
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
86 config_value.source = config_file;
137
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
86 config_value.value = value;
138
2/4
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 5 not taken.
86 PopulateParameter(parameter, config_value);
139
4/4
✓ Branch 3 taken 86 times.
✓ Branch 4 taken 30 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 30 times.
146 }
140
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 fclose(fconfig);
141 8 return true;
142 9 }
143
144 1013 void BashOptionsManager::ParsePath(const string &config_file,
145 const bool external) {
146
1/2
✓ Branch 2 taken 1013 times.
✗ Branch 3 not taken.
1013 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 1013 pid_t pid_child = 0;
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1013 times.
1013 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 1013 times.
✗ Branch 2 not taken.
1013 const string config_path = GetParentPath(config_file);
186
1/2
✓ Branch 2 taken 1013 times.
✗ Branch 3 not taken.
1013 FILE *fconfig = fopen(config_file.c_str(), "r");
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1013 times.
1013 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 49 times.
✓ Branch 1 taken 964 times.
1013 if (!fconfig) {
195
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 49 times.
49 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 49 return;
213 }
214
215 int fd_stdin;
216 int fd_stdout;
217 int fd_stderr;
218
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
964 retval = Shell(&fd_stdin, &fd_stdout, &fd_stderr);
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 964 times.
964 assert(retval);
220
221 // Let the shell read the file
222 1928 string line;
223
1/2
✓ Branch 2 taken 964 times.
✗ Branch 3 not taken.
1928 const string newline = "\n";
224
5/15
✗ Branch 1 not taken.
✓ Branch 2 taken 964 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 964 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 964 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 964 times.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 964 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1928 const string cd = "cd \"" + ((config_path == "") ? "/" : config_path) + "\""
225
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
1928 + newline;
226
1/2
✓ Branch 3 taken 964 times.
✗ Branch 4 not taken.
964 WritePipe(fd_stdin, cd.data(), cd.length());
227
3/4
✓ Branch 1 taken 11796 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10832 times.
✓ Branch 4 taken 964 times.
11796 while (GetLineFile(fconfig, &line)) {
228
1/2
✓ Branch 3 taken 10832 times.
✗ Branch 4 not taken.
10832 WritePipe(fd_stdin, line.data(), line.length());
229
1/2
✓ Branch 3 taken 10832 times.
✗ Branch 4 not taken.
10832 WritePipe(fd_stdin, newline.data(), newline.length());
230 }
231
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
964 rewind(fconfig);
232
233 // Read line by line and extract parameters
234
3/4
✓ Branch 1 taken 11796 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10832 times.
✓ Branch 4 taken 964 times.
11796 while (GetLineFile(fconfig, &line)) {
235 10832 vector<string> tokens;
236
1/2
✓ Branch 1 taken 10832 times.
✗ Branch 2 not taken.
10832 const string parameter = SanitizeParameterAssignment(&line, &tokens);
237
2/2
✓ Branch 1 taken 1470 times.
✓ Branch 2 taken 9362 times.
10832 if (parameter.empty())
238 1470 continue;
239
240 9362 ConfigValue value;
241
1/2
✓ Branch 1 taken 9362 times.
✗ Branch 2 not taken.
9362 value.source = config_file;
242
2/4
✓ Branch 1 taken 9362 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9362 times.
✗ Branch 5 not taken.
9362 const string sh_echo = "echo $" + parameter + "\n";
243
1/2
✓ Branch 3 taken 9362 times.
✗ Branch 4 not taken.
9362 WritePipe(fd_stdin, sh_echo.data(), sh_echo.length());
244
1/2
✓ Branch 1 taken 9362 times.
✗ Branch 2 not taken.
9362 GetLineFd(fd_stdout, &value.value);
245
2/4
✓ Branch 1 taken 9362 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9362 times.
✗ Branch 5 not taken.
9362 PopulateParameter(parameter, value);
246
4/4
✓ Branch 3 taken 9362 times.
✓ Branch 4 taken 1470 times.
✓ Branch 6 taken 9362 times.
✓ Branch 7 taken 1470 times.
12302 }
247
248
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
964 close(fd_stderr);
249
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
964 close(fd_stdout);
250
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
964 close(fd_stdin);
251
1/2
✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
964 fclose(fconfig);
252 }
253
254
255 1411 bool OptionsManager::HasConfigRepository(const string &fqrn,
256 string *config_path) {
257 1411 string cvmfs_mount_dir;
258
3/6
✓ Branch 2 taken 1411 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1411 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1411 times.
1411 if (!GetValue("CVMFS_MOUNT_DIR", &cvmfs_mount_dir)) {
259 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "CVMFS_MOUNT_DIR missing");
260 ✗ return false;
261 }
262
263 1411 string config_repository;
264
4/6
✓ Branch 2 taken 1411 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1411 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 111 times.
✓ Branch 10 taken 1300 times.
1411 if (GetValue("CVMFS_CONFIG_REPOSITORY", &config_repository)) {
265
3/6
✓ Branch 1 taken 111 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 111 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 111 times.
111 if (config_repository.empty() || (config_repository == fqrn))
266 ✗ return false;
267
1/2
✓ Branch 1 taken 111 times.
✗ Branch 2 not taken.
111 const sanitizer::RepositorySanitizer repository_sanitizer;
268
2/4
✓ Branch 1 taken 111 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 111 times.
111 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 111 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 111 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 111 times.
✗ Branch 8 not taken.
111 *config_path = cvmfs_mount_dir + "/" + config_repository + "/etc/cvmfs/";
275 111 return true;
276 111 }
277 1300 return false;
278 1411 }
279
280 ✗ void OptionsManager::SetupGlobalEnvironmentParams() {
281 ✗ SetValue("CVMFS_ARCH", GetArch());
282
283 // Set CVMFS_VERSION environment variable
284 ✗ SetValue("CVMFS_VERSION", CVMFS_VERSION);
285
286 // Calculate and set CVMFS_VERSION_NUMERIC
287 // Format: major * 10000 + minor * 100 + patch
288 // Example: 2.13.2 becomes 21302
289 ✗ const int version_numeric = CVMFS_VERSION_MAJOR * 10000
290 + CVMFS_VERSION_MINOR * 100 + CVMFS_VERSION_PATCH;
291 char version_numeric_str[16];
292 ✗ snprintf(version_numeric_str, sizeof(version_numeric_str), "%d",
293 version_numeric);
294 ✗ SetValue("CVMFS_VERSION_NUMERIC", version_numeric_str);
295 }
296
297 ✗ void OptionsManager::ParseDefault(const string &fqrn) {
298 ✗ if (taint_environment_) {
299 ✗ const int retval = setenv("CVMFS_FQRN", fqrn.c_str(), 1);
300 ✗ assert(retval == 0);
301 }
302
303 ✗ SetupGlobalEnvironmentParams();
304 ✗ protected_parameters_.clear();
305 ✗ ParsePath("/etc/cvmfs/default.conf", false);
306 vector<string> dist_defaults = FindFilesBySuffix("/etc/cvmfs/default.d",
307 ✗ ".conf");
308 ✗ for (unsigned i = 0; i < dist_defaults.size(); ++i) {
309 ✗ ParsePath(dist_defaults[i], false);
310 }
311 ✗ ProtectParameter("CVMFS_CONFIG_REPOSITORY");
312 ✗ string external_config_path;
313 ✗ if ((fqrn != "") && HasConfigRepository(fqrn, &external_config_path))
314 ✗ ParsePath(external_config_path + "default.conf", true);
315 ✗ ParsePath("/etc/cvmfs/default.local", false);
316
317 ✗ if (fqrn != "") {
318 ✗ string domain;
319 ✗ vector<string> tokens = SplitString(fqrn, '.');
320 ✗ assert(tokens.size() > 1);
321 ✗ tokens.erase(tokens.begin());
322 ✗ domain = JoinStrings(tokens, ".");
323
324 ✗ if (HasConfigRepository(fqrn, &external_config_path))
325 ✗ ParsePath(external_config_path + "domain.d/" + domain + ".conf", true);
326 ✗ ParsePath("/etc/cvmfs/domain.d/" + domain + ".conf", false);
327 ✗ ParsePath("/etc/cvmfs/domain.d/" + domain + ".local", false);
328
329 ✗ if (HasConfigRepository(fqrn, &external_config_path))
330 ✗ ParsePath(external_config_path + "config.d/" + fqrn + ".conf", true);
331 ✗ ParsePath("/etc/cvmfs/config.d/" + fqrn + ".conf", false);
332 ✗ ParsePath("/etc/cvmfs/config.d/" + fqrn + ".local", false);
333 }
334 }
335
336
337 20814 void OptionsManager::PopulateParameter(const string &param, ConfigValue val) {
338
1/2
✓ Branch 1 taken 20814 times.
✗ Branch 2 not taken.
20814 const map<string, string>::const_iterator iter = protected_parameters_.find(
339 20814 param);
340
5/6
✓ Branch 3 taken 50 times.
✓ Branch 4 taken 20764 times.
✓ Branch 7 taken 50 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 50 times.
✓ Branch 10 taken 20764 times.
20814 if ((iter != protected_parameters_.end()) && (iter->second != val.value)) {
341
1/3
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
100 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
342 "error in cvmfs configuration: attempt to change protected %s "
343 "from %s to %s",
344 50 param.c_str(), iter->second.c_str(), val.value.c_str());
345 50 return;
346 }
347
2/4
✓ Branch 1 taken 20764 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20764 times.
✗ Branch 5 not taken.
20764 ParseValue(param, &val);
348
2/4
✓ Branch 1 taken 20764 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20764 times.
✗ Branch 5 not taken.
20764 config_[param] = val;
349
1/2
✓ Branch 1 taken 20764 times.
✗ Branch 2 not taken.
20764 UpdateEnvironment(param, val);
350 }
351
352 20820 void OptionsManager::UpdateEnvironment(const string &param, ConfigValue val) {
353
2/2
✓ Branch 0 taken 20448 times.
✓ Branch 1 taken 372 times.
20820 if (taint_environment_) {
354 20448 const int retval = setenv(param.c_str(), val.value.c_str(), 1);
355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20448 times.
20448 assert(retval == 0);
356 }
357 20820 }
358
359 20764 void OptionsManager::ParseValue(std::string param, ConfigValue *val) {
360
1/2
✓ Branch 1 taken 20764 times.
✗ Branch 2 not taken.
20764 const string orig = val->value;
361
1/2
✓ Branch 1 taken 20764 times.
✗ Branch 2 not taken.
20764 const bool has_templ = opt_templ_mgr_->ParseString(&(val->value));
362
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 20458 times.
20764 if (has_templ) {
363
2/4
✓ Branch 1 taken 306 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 306 times.
✗ Branch 5 not taken.
306 templatable_values_[param] = orig;
364 }
365 20764 }
366
367
368 50 void OptionsManager::ProtectParameter(const string &param) {
369 50 string value;
370 // We don't care about the result. If param does not yet exists, we lock it
371 // to the empty string.
372
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
50 (void)GetValue(param, &value);
373
2/4
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
50 protected_parameters_[param] = value;
374 50 }
375
376
377 50 void OptionsManager::ClearConfig() { config_.clear(); }
378
379
380 12094 bool OptionsManager::IsDefined(const std::string &key) {
381
1/2
✓ Branch 1 taken 12094 times.
✗ Branch 2 not taken.
12094 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
382 12094 return iter != config_.end();
383 }
384
385
386 153387 bool OptionsManager::GetValue(const string &key, string *value) const {
387
1/2
✓ Branch 1 taken 153387 times.
✗ Branch 2 not taken.
153387 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
388
2/2
✓ Branch 2 taken 37805 times.
✓ Branch 3 taken 115582 times.
153387 if (iter != config_.end()) {
389
1/2
✓ Branch 2 taken 37805 times.
✗ Branch 3 not taken.
37805 *value = iter->second.value;
390 37805 return true;
391 }
392
1/2
✓ Branch 1 taken 115582 times.
✗ Branch 2 not taken.
115582 *value = "";
393 115582 return false;
394 }
395
396
397 57 std::string OptionsManager::GetValueOrDie(const string &key) {
398 57 std::string value;
399
1/2
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
57 const bool retval = GetValue(key, &value);
400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!retval) {
401 ✗ PANIC(kLogStderr | kLogDebug, "%s configuration parameter missing",
402 key.c_str());
403 }
404 57 return value;
405 }
406
407
408 14593 bool OptionsManager::GetSource(const string &key, string *value) {
409
1/2
✓ Branch 1 taken 14593 times.
✗ Branch 2 not taken.
14593 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
410
1/2
✓ Branch 3 taken 14593 times.
✗ Branch 4 not taken.
14593 if (iter != config_.end()) {
411
1/2
✓ Branch 2 taken 14593 times.
✗ Branch 3 not taken.
14593 *value = iter->second.source;
412 14593 return true;
413 }
414 ✗ *value = "";
415 ✗ return false;
416 }
417
418
419 3737 bool OptionsManager::IsOn(const std::string &param_value) const {
420
1/2
✓ Branch 1 taken 3737 times.
✗ Branch 2 not taken.
3737 const string uppercase = ToUpper(param_value);
421
2/4
✓ Branch 2 taken 3441 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3441 times.
✗ Branch 6 not taken.
7178 return ((uppercase == "YES") || (uppercase == "ON") || (uppercase == "1")
422
3/4
✓ Branch 0 taken 3441 times.
✓ Branch 1 taken 296 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3441 times.
10915 || (uppercase == "TRUE"));
423 3737 }
424
425
426 72 bool OptionsManager::IsOff(const std::string &param_value) const {
427
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 const string uppercase = ToUpper(param_value);
428
3/4
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 36 times.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
144 return ((uppercase == "NO") || (uppercase == "OFF") || (uppercase == "0")
429
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
216 || (uppercase == "FALSE"));
430 72 }
431
432
433 2363 vector<string> OptionsManager::GetAllKeys() {
434 2363 vector<string> result;
435 2363 for (map<string, ConfigValue>::const_iterator i = config_.begin(),
436 2363 iEnd = config_.end();
437
2/2
✓ Branch 1 taken 14993 times.
✓ Branch 2 taken 2363 times.
17356 i != iEnd;
438 14993 ++i) {
439
1/2
✓ Branch 2 taken 14993 times.
✗ Branch 3 not taken.
14993 result.push_back(i->first);
440 }
441 2363 return result;
442 }
443
444
445 372 vector<string> OptionsManager::GetEnvironmentSubset(const string &key_prefix,
446 bool strip_prefix) {
447 372 vector<string> result;
448 372 for (map<string, ConfigValue>::const_iterator i = config_.begin(),
449 372 iEnd = config_.end();
450
2/2
✓ Branch 1 taken 2800 times.
✓ Branch 2 taken 372 times.
3172 i != iEnd;
451 2800 ++i) {
452 2800 const bool ignore_prefix = false;
453
3/4
✓ Branch 2 taken 2800 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 350 times.
✓ Branch 5 taken 2450 times.
2800 if (HasPrefix(i->first, key_prefix, ignore_prefix)) {
454 const string output_key = strip_prefix
455 50 ? i->first.substr(key_prefix.length())
456
4/6
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 300 times.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 300 times.
✗ Branch 9 not taken.
400 : i->first;
457
3/6
✓ Branch 2 taken 350 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 350 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 350 times.
✗ Branch 9 not taken.
350 result.push_back(output_key + "=" + i->second.value);
458 350 }
459 }
460 372 return result;
461 }
462
463
464 2263 string OptionsManager::Dump() {
465 2263 string result;
466
1/2
✓ Branch 1 taken 2263 times.
✗ Branch 2 not taken.
2263 vector<string> keys = GetAllKeys();
467
2/2
✓ Branch 1 taken 14293 times.
✓ Branch 2 taken 2263 times.
16556 for (unsigned i = 0, l = keys.size(); i < l; ++i) {
468 bool retval;
469 14293 string value;
470 14293 string source;
471
472
1/2
✓ Branch 2 taken 14293 times.
✗ Branch 3 not taken.
14293 retval = GetValue(keys[i], &value);
473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14293 times.
14293 assert(retval);
474
1/2
✓ Branch 2 taken 14293 times.
✗ Branch 3 not taken.
14293 retval = GetSource(keys[i], &source);
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14293 times.
14293 assert(retval);
476
5/10
✓ Branch 1 taken 14293 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 14293 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 14293 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 14293 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 14293 times.
✗ Branch 15 not taken.
28586 result += keys[i] + "=" + EscapeShell(value) + " # from " + source
477
2/4
✓ Branch 1 taken 14293 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14293 times.
✗ Branch 5 not taken.
14293 + "\n";
478 14293 }
479 4526 return result;
480 2263 }
481
482 ✗ void OptionsManager::SetValueFromTalk(const string &key, const string &value) {
483 ✗ ConfigValue config_value;
484 ✗ config_value.source = "cvmfs_talk";
485 ✗ config_value.value = value;
486 ✗ PopulateParameter(key, config_value);
487 }
488
489 11366 void OptionsManager::SetValue(const string &key, const string &value) {
490 11366 ConfigValue config_value;
491
1/2
✓ Branch 1 taken 11366 times.
✗ Branch 2 not taken.
11366 config_value.source = "@INTERNAL@";
492
1/2
✓ Branch 1 taken 11366 times.
✗ Branch 2 not taken.
11366 config_value.value = value;
493
2/4
✓ Branch 1 taken 11366 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11366 times.
✗ Branch 5 not taken.
11366 PopulateParameter(key, config_value);
494 11366 }
495
496
497 650 void OptionsManager::UnsetValue(const string &key) {
498 650 protected_parameters_.erase(key);
499 650 config_.erase(key);
500
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 50 times.
650 if (taint_environment_)
501 600 unsetenv(key.c_str());
502 650 }
503
504 const char *DefaultOptionsTemplateManager ::kTemplateIdentFqrn = "fqrn";
505
506 const char *DefaultOptionsTemplateManager ::kTemplateIdentOrg = "org";
507
508 666 DefaultOptionsTemplateManager::DefaultOptionsTemplateManager(std::string fqrn) {
509
3/6
✓ Branch 1 taken 666 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 666 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 666 times.
✗ Branch 9 not taken.
666 SetTemplate(kTemplateIdentFqrn, fqrn);
510
1/2
✓ Branch 1 taken 666 times.
✗ Branch 2 not taken.
666 vector<string> fqrn_parts = SplitString(fqrn, '.');
511
3/6
✓ Branch 2 taken 666 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 666 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 666 times.
✗ Branch 10 not taken.
666 SetTemplate(kTemplateIdentOrg, fqrn_parts[0]);
512 666 }
513
514 1458 void OptionsTemplateManager::SetTemplate(std::string name, std::string val) {
515 1458 templates_[name] = val;
516 1458 }
517
518 1290 std::string OptionsTemplateManager::GetTemplate(std::string name) {
519
2/2
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 1032 times.
1290 if (templates_.count(name)) {
520 258 return templates_[name];
521 } else {
522
2/4
✓ Branch 1 taken 1032 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1032 times.
✗ Branch 5 not taken.
1032 std::string var_name = "@" + name + "@";
523
1/2
✓ Branch 2 taken 1032 times.
✗ Branch 3 not taken.
1032 LogCvmfs(kLogCvmfs, kLogDebug, "Undeclared variable: %s", var_name.c_str());
524 1032 return var_name;
525 1032 }
526 }
527
528 20896 bool OptionsTemplateManager::ParseString(std::string *input) {
529 20896 std::string result;
530
1/2
✓ Branch 1 taken 20896 times.
✗ Branch 2 not taken.
20896 std::string in = *input;
531 20896 bool has_vars = false;
532 20896 int mode = 0;
533 20896 std::string stock;
534
2/2
✓ Branch 1 taken 556128 times.
✓ Branch 2 taken 20896 times.
577024 for (std::string::size_type i = 0; i < in.size(); i++) {
535
2/3
✓ Branch 0 taken 548892 times.
✓ Branch 1 taken 7236 times.
✗ Branch 2 not taken.
556128 switch (mode) {
536 548892 case 0:
537
3/4
✓ Branch 1 taken 548892 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1495 times.
✓ Branch 4 taken 547397 times.
548892 if (in[i] == '@') {
538 1495 mode = 1;
539 } else {
540
2/4
✓ Branch 1 taken 547397 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 547397 times.
✗ Branch 5 not taken.
547397 result += in[i];
541 }
542 548892 break;
543 7236 case 1:
544
3/4
✓ Branch 1 taken 7236 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1157 times.
✓ Branch 4 taken 6079 times.
7236 if (in[i] == '@') {
545 1157 mode = 0;
546
3/6
✓ Branch 1 taken 1157 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1157 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1157 times.
✗ Branch 8 not taken.
1157 result += GetTemplate(stock);
547
1/2
✓ Branch 1 taken 1157 times.
✗ Branch 2 not taken.
1157 stock = "";
548 1157 has_vars = true;
549 } else {
550
2/4
✓ Branch 1 taken 6079 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6079 times.
✗ Branch 5 not taken.
6079 stock += in[i];
551 }
552 7236 break;
553 }
554 }
555
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 20558 times.
20896 if (mode == 1) {
556
2/4
✓ Branch 1 taken 338 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 338 times.
✗ Branch 5 not taken.
338 result += "@" + stock;
557 }
558
1/2
✓ Branch 1 taken 20896 times.
✗ Branch 2 not taken.
20896 *input = result;
559 20896 return has_vars;
560 20896 }
561
562 133 bool OptionsTemplateManager::HasTemplate(std::string name) {
563 133 return templates_.count(name);
564 }
565
566 #ifdef CVMFS_NAMESPACE_GUARD
567 } // namespace CVMFS_NAMESPACE_GUARD
568 #endif
569