GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/options.cc
Date: 2026-11-01 02:41:19
Exec Total Coverage
Lines: 278 365 76.2%
Branches: 284 681 41.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 19260 static string EscapeShell(const std::string &raw) {
35
2/2
✓ Branch 1 taken 255659 times.
✓ Branch 2 taken 18906 times.
274565 for (unsigned i = 0, l = raw.length(); i < l; ++i) {
36
6/6
✓ Branch 1 taken 224644 times.
✓ Branch 2 taken 31015 times.
✓ Branch 4 taken 196939 times.
✓ Branch 5 taken 27705 times.
✓ Branch 6 taken 354 times.
✓ Branch 7 taken 255305 times.
483613 if (!(((raw[i] >= '0') && (raw[i] <= '9'))
37
4/4
✓ Branch 1 taken 195873 times.
✓ Branch 2 taken 32081 times.
✓ Branch 4 taken 179813 times.
✓ Branch 5 taken 16060 times.
227954 || ((raw[i] >= 'A') && (raw[i] <= 'Z'))
38
5/6
✓ Branch 1 taken 167869 times.
✓ Branch 2 taken 44025 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 167869 times.
✓ Branch 7 taken 23647 times.
✓ Branch 8 taken 20378 times.
211894 || ((raw[i] >= 'a') && (raw[i] <= 'z')) || (raw[i] == '/')
39
6/6
✓ Branch 1 taken 22830 times.
✓ Branch 2 taken 817 times.
✓ Branch 4 taken 12650 times.
✓ Branch 5 taken 10180 times.
✓ Branch 7 taken 706 times.
✓ Branch 8 taken 11944 times.
23647 || (raw[i] == ':') || (raw[i] == '.') || (raw[i] == '_')
40
3/4
✓ Branch 1 taken 354 times.
✓ Branch 2 taken 352 times.
✓ Branch 4 taken 354 times.
✗ Branch 5 not taken.
706 || (raw[i] == '-') || (raw[i] == ','))) {
41 354 goto escape_shell_quote;
42 }
43 }
44
1/2
✓ Branch 1 taken 18906 times.
✗ Branch 2 not taken.
18906 return raw;
45
46 354 escape_shell_quote:
47
1/2
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
708 string result = "'";
48
2/2
✓ Branch 1 taken 8746 times.
✓ Branch 2 taken 354 times.
9100 for (unsigned i = 0, l = raw.length(); i < l; ++i) {
49
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8746 times.
8746 if (raw[i] == '\'')
50 ✗ result += "\\";
51
1/2
✓ Branch 2 taken 8746 times.
✗ Branch 3 not taken.
8746 result += raw[i];
52 }
53
1/2
✓ Branch 1 taken 354 times.
✗ Branch 2 not taken.
354 result += "'";
54 354 return result;
55 }
56
57
58 12341 string OptionsManager::TrimParameter(const string &parameter) {
59 12341 string result = Trim(parameter);
60 // Strip "readonly"
61
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12341 times.
12341 if (result.find("readonly ") == 0) {
62 ✗ result = result.substr(9);
63 ✗ result = Trim(result);
64
2/2
✓ Branch 1 taken 732 times.
✓ Branch 2 taken 11609 times.
12341 } else if (result.find("export ") == 0) {
65
1/2
✓ Branch 1 taken 732 times.
✗ Branch 2 not taken.
732 result = result.substr(7);
66
1/2
✓ Branch 1 taken 732 times.
✗ Branch 2 not taken.
732 result = Trim(result);
67 // This enables a hack to ignore a variable setting in cvmfs versions
68 // prior to 2.14.2 which also stopped setting variables to blank when
69 // they are defined only in false conditionals. The hack is to use
70 // 'export X VAR=VAL', where VAR will be recognized in 2.14.2 and later
71 // and ignored prior to 2.14.2.
72 732 const size_t last_space = result.find_last_of(" ");
73
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 366 times.
732 if (last_space != string::npos) {
74
1/2
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
366 result = result.substr(last_space + 1);
75 }
76
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11609 times.
11609 } else if (result.find("eval ") == 0) {
77 ✗ result = result.substr(5);
78 ✗ result = Trim(result);
79 }
80 12341 return result;
81 }
82
83 14903 string OptionsManager::SanitizeParameterAssignment(string *line,
84 vector<string> *tokens) {
85 14903 const size_t comment_idx = line->find("#");
86
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 14171 times.
14903 if (comment_idx != string::npos)
87
1/2
✓ Branch 1 taken 732 times.
✗ Branch 2 not taken.
732 *line = line->substr(0, comment_idx);
88
1/2
✓ Branch 1 taken 14903 times.
✗ Branch 2 not taken.
14903 *line = Trim(*line);
89
2/2
✓ Branch 1 taken 732 times.
✓ Branch 2 taken 14171 times.
14903 if (line->empty())
90
1/2
✓ Branch 2 taken 732 times.
✗ Branch 3 not taken.
732 return "";
91
1/2
✓ Branch 1 taken 14171 times.
✗ Branch 2 not taken.
14171 *tokens = SplitString(*line, '=');
92
2/2
✓ Branch 1 taken 1830 times.
✓ Branch 2 taken 12341 times.
14171 if (tokens->size() < 2)
93
1/2
✓ Branch 2 taken 1830 times.
✗ Branch 3 not taken.
1830 return "";
94
1/2
✓ Branch 2 taken 12341 times.
✗ Branch 3 not taken.
12341 string parameter = TrimParameter((*tokens)[0]);
95
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12341 times.
12341 if (parameter.find(" ") != string::npos)
96 ✗ return "";
97 12341 return parameter;
98 12341 }
99
100 233 void OptionsManager::SwitchTemplateManager(
101 OptionsTemplateManager *opt_templ_mgr_param) {
102
1/2
✓ Branch 0 taken 233 times.
✗ Branch 1 not taken.
233 delete opt_templ_mgr_;
103
1/2
✓ Branch 0 taken 233 times.
✗ Branch 1 not taken.
233 if (opt_templ_mgr_param != NULL) {
104 233 opt_templ_mgr_ = opt_templ_mgr_param;
105 } else {
106 ✗ opt_templ_mgr_ = new OptionsTemplateManager();
107 }
108 233 for (std::map<std::string, std::string>::iterator it =
109 233 templatable_values_.begin();
110
2/2
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 233 times.
338 it != templatable_values_.end();
111 105 it++) {
112
2/4
✓ Branch 3 taken 105 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 105 times.
✗ Branch 7 not taken.
105 config_[it->first].value = it->second;
113
2/4
✓ Branch 2 taken 105 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 105 times.
✗ Branch 6 not taken.
105 opt_templ_mgr_->ParseString(&(config_[it->first].value));
114
2/4
✓ Branch 2 taken 105 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 105 times.
✗ Branch 6 not taken.
105 UpdateEnvironment(it->first, config_[it->first]);
115 }
116 233 }
117
118 360 bool SimpleOptionsParser::TryParsePath(const string &config_file) {
119
1/2
✓ Branch 2 taken 360 times.
✗ Branch 3 not taken.
360 LogCvmfs(kLogCvmfs, kLogDebug, "Fast-parsing config file %s",
120 config_file.c_str());
121 360 string line;
122
1/2
✓ Branch 2 taken 360 times.
✗ Branch 3 not taken.
360 FILE *fconfig = fopen(config_file.c_str(), "r");
123
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 320 times.
360 if (fconfig == NULL)
124 40 return false;
125
126 // Read line by line and extract parameters
127
3/4
✓ Branch 1 taken 6640 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6320 times.
✓ Branch 4 taken 320 times.
6640 while (GetLineFile(fconfig, &line)) {
128 6320 vector<string> tokens;
129
1/2
✓ Branch 1 taken 6320 times.
✗ Branch 2 not taken.
6320 const string parameter = SanitizeParameterAssignment(&line, &tokens);
130
2/2
✓ Branch 1 taken 2160 times.
✓ Branch 2 taken 4160 times.
6320 if (parameter.empty())
131 2160 continue;
132
133 // Strip quotes from value
134
1/2
✓ Branch 3 taken 4160 times.
✗ Branch 4 not taken.
4160 tokens.erase(tokens.begin());
135
3/6
✓ Branch 2 taken 4160 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4160 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4160 times.
✗ Branch 9 not taken.
8320 string value = Trim(JoinStrings(tokens, "="));
136 4160 const unsigned value_length = value.length();
137
2/2
✓ Branch 0 taken 2960 times.
✓ Branch 1 taken 1200 times.
4160 if (value_length > 2) {
138
3/7
✓ Branch 1 taken 2960 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 240 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 240 times.
3200 if (((value[0] == '"') && ((value[value_length - 1] == '"')))
139
9/13
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 2720 times.
✓ Branch 3 taken 2720 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 240 times.
✓ Branch 6 taken 2480 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 240 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 240 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 480 times.
✓ Branch 13 taken 2480 times.
3200 || ((value[0] == '\'') && ((value[value_length - 1] == '\'')))) {
140
1/2
✓ Branch 1 taken 480 times.
✗ Branch 2 not taken.
480 value = value.substr(1, value_length - 2);
141 }
142 }
143
144 4160 ConfigValue config_value;
145
1/2
✓ Branch 1 taken 4160 times.
✗ Branch 2 not taken.
4160 config_value.source = config_file;
146
1/2
✓ Branch 1 taken 4160 times.
✗ Branch 2 not taken.
4160 config_value.value = value;
147
2/4
✓ Branch 1 taken 4160 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4160 times.
✗ Branch 5 not taken.
4160 PopulateParameter(parameter, config_value);
148
4/4
✓ Branch 3 taken 4160 times.
✓ Branch 4 taken 2160 times.
✓ Branch 6 taken 4160 times.
✓ Branch 7 taken 2160 times.
8480 }
149
1/2
✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
320 fclose(fconfig);
150 320 return true;
151 360 }
152
153 774 void BashOptionsManager::ParsePath(const string &config_file,
154 const bool external) {
155
1/2
✓ Branch 2 taken 774 times.
✗ Branch 3 not taken.
774 LogCvmfs(kLogCvmfs, kLogDebug, "Parsing config file %s", config_file.c_str());
156 int retval;
157 int pipe_open[2];
158 int pipe_quit[2];
159 774 pid_t pid_child = 0;
160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 774 times.
774 if (external) {
161 // cvmfs can run in the process group of automount in which case
162 // autofs won't mount an additional config repository. We create a
163 // short-lived process that detaches from the process group and triggers
164 // autofs to mount the config repository, if necessary. It holds a file
165 // handle to the config file until the main process opened the file, too.
166 ✗ MakePipe(pipe_open);
167 ✗ MakePipe(pipe_quit);
168 ✗ switch (pid_child = fork()) {
169 ✗ case -1:
170 ✗ PANIC(NULL);
171 ✗ case 0: { // Child
172 ✗ close(pipe_open[0]);
173 ✗ close(pipe_quit[1]);
174 // If this is not a process group leader, create a new session
175 ✗ if (getpgrp() != getpid()) {
176 ✗ const pid_t new_session = setsid();
177 ✗ assert(new_session != (pid_t)-1);
178 }
179 ✗ (void)open(config_file.c_str(), O_RDONLY);
180 ✗ char ready = 'R';
181 ✗ WritePipe(pipe_open[1], &ready, 1);
182 ✗ retval = read(pipe_quit[0], &ready, 1);
183 ✗ _exit(retval); // Don't flush shared file descriptors
184 }
185 }
186 // Parent
187 ✗ close(pipe_open[1]);
188 ✗ close(pipe_quit[0]);
189 ✗ char ready = 0;
190 ✗ ReadPipe(pipe_open[0], &ready, 1);
191 ✗ assert(ready == 'R');
192 ✗ close(pipe_open[0]);
193 }
194
1/2
✓ Branch 1 taken 774 times.
✗ Branch 2 not taken.
774 const string config_path = GetParentPath(config_file);
195
1/2
✓ Branch 2 taken 774 times.
✗ Branch 3 not taken.
774 FILE *fconfig = fopen(config_file.c_str(), "r");
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 774 times.
774 if (pid_child > 0) {
197 ✗ char c = 'C';
198 ✗ WritePipe(pipe_quit[1], &c, 1);
199 int statloc;
200 ✗ waitpid(pid_child, &statloc, 0);
201 ✗ close(pipe_quit[1]);
202 }
203
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 753 times.
774 if (!fconfig) {
204
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 21 times.
21 if (external && !DirectoryExists(config_path)) {
205 ✗ string repo_required;
206 ✗ if (GetValue("CVMFS_CONFIG_REPO_REQUIRED", &repo_required)
207 ✗ && IsOn(repo_required)) {
208 ✗ LogCvmfs(
209 kLogCvmfs, kLogStderr | kLogSyslogErr,
210 "required configuration repository directory does not exist: %s",
211 config_path.c_str());
212 // Do not crash as in abort(), which can trigger core file creation
213 // from the mount helper
214 ✗ exit(1);
215 }
216
217 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogWarn,
218 "configuration repository directory does not exist: %s",
219 config_path.c_str());
220 }
221 21 return;
222 }
223
224 int fd_stdin;
225 int fd_stdout;
226 int fd_stderr;
227
1/2
✓ Branch 1 taken 753 times.
✗ Branch 2 not taken.
753 retval = Shell(&fd_stdin, &fd_stdout, &fd_stderr);
228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 753 times.
753 assert(retval);
229
230 // Let the shell read the file
231 1506 string line;
232
1/2
✓ Branch 2 taken 753 times.
✗ Branch 3 not taken.
1506 const string newline = "\n";
233
5/15
✗ Branch 1 not taken.
✓ Branch 2 taken 753 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 753 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 753 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 753 times.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 753 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1506 const string cd = "cd \"" + ((config_path == "") ? "/" : config_path) + "\""
234
1/2
✓ Branch 1 taken 753 times.
✗ Branch 2 not taken.
1506 + newline;
235
1/2
✓ Branch 3 taken 753 times.
✗ Branch 4 not taken.
753 WritePipe(fd_stdin, cd.data(), cd.length());
236
3/4
✓ Branch 1 taken 9336 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8583 times.
✓ Branch 4 taken 753 times.
9336 while (GetLineFile(fconfig, &line)) {
237
1/2
✓ Branch 3 taken 8583 times.
✗ Branch 4 not taken.
8583 WritePipe(fd_stdin, line.data(), line.length());
238
1/2
✓ Branch 3 taken 8583 times.
✗ Branch 4 not taken.
8583 WritePipe(fd_stdin, newline.data(), newline.length());
239 }
240
1/2
✓ Branch 1 taken 753 times.
✗ Branch 2 not taken.
753 rewind(fconfig);
241
242 // Read line by line and extract parameters
243
3/4
✓ Branch 1 taken 9336 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8583 times.
✓ Branch 4 taken 753 times.
9336 while (GetLineFile(fconfig, &line)) {
244 8583 vector<string> tokens;
245
1/2
✓ Branch 1 taken 8583 times.
✗ Branch 2 not taken.
8583 const string parameter = SanitizeParameterAssignment(&line, &tokens);
246
2/2
✓ Branch 1 taken 1134 times.
✓ Branch 2 taken 7449 times.
8583 if (parameter.empty())
247 1134 continue;
248
249 7449 ConfigValue value;
250
1/2
✓ Branch 1 taken 7449 times.
✗ Branch 2 not taken.
7449 value.source = config_file;
251
2/4
✓ Branch 1 taken 7449 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7449 times.
✗ Branch 5 not taken.
7449 const string sh_echo = "echo ${" + parameter + "-xNOTxSETx}\n";
252
1/2
✓ Branch 3 taken 7449 times.
✗ Branch 4 not taken.
7449 WritePipe(fd_stdin, sh_echo.data(), sh_echo.length());
253
1/2
✓ Branch 1 taken 7449 times.
✗ Branch 2 not taken.
7449 GetLineFd(fd_stdout, &value.value);
254
1/2
✓ Branch 1 taken 7449 times.
✗ Branch 2 not taken.
7449 if (value.value != "xNOTxSETx") {
255
2/4
✓ Branch 1 taken 7449 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7449 times.
✗ Branch 5 not taken.
7449 PopulateParameter(parameter, value);
256 }
257
4/4
✓ Branch 3 taken 7449 times.
✓ Branch 4 taken 1134 times.
✓ Branch 6 taken 7449 times.
✓ Branch 7 taken 1134 times.
9717 }
258
259
1/2
✓ Branch 1 taken 753 times.
✗ Branch 2 not taken.
753 close(fd_stderr);
260
1/2
✓ Branch 1 taken 753 times.
✗ Branch 2 not taken.
753 close(fd_stdout);
261
1/2
✓ Branch 1 taken 753 times.
✗ Branch 2 not taken.
753 close(fd_stdin);
262
1/2
✓ Branch 1 taken 753 times.
✗ Branch 2 not taken.
753 fclose(fconfig);
263 }
264
265
266 1668 bool OptionsManager::HasConfigRepository(const string &fqrn,
267 string *config_path) {
268 1668 string cvmfs_mount_dir;
269
3/6
✓ Branch 2 taken 1668 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1668 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1668 times.
1668 if (!GetValue("CVMFS_MOUNT_DIR", &cvmfs_mount_dir)) {
270 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "CVMFS_MOUNT_DIR missing");
271 ✗ return false;
272 }
273
274 1668 string config_repository;
275
4/6
✓ Branch 2 taken 1668 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1668 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 132 times.
✓ Branch 10 taken 1536 times.
1668 if (GetValue("CVMFS_CONFIG_REPOSITORY", &config_repository)) {
276
3/6
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 132 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 132 times.
132 if (config_repository.empty() || (config_repository == fqrn))
277 ✗ return false;
278
1/2
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
132 const sanitizer::RepositorySanitizer repository_sanitizer;
279
2/4
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 132 times.
132 if (!repository_sanitizer.IsValid(config_repository)) {
280 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
281 "invalid CVMFS_CONFIG_REPOSITORY: %s",
282 config_repository.c_str());
283 ✗ return false;
284 }
285
3/6
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 132 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 132 times.
✗ Branch 8 not taken.
132 *config_path = cvmfs_mount_dir + "/" + config_repository + "/etc/cvmfs/";
286 132 return true;
287 132 }
288 1536 return false;
289 1668 }
290
291 ✗ void OptionsManager::SetupGlobalEnvironmentParams() {
292 ✗ SetValue("CVMFS_ARCH", GetArch());
293
294 // Set CVMFS_VERSION environment variable
295 ✗ SetValue("CVMFS_VERSION", CVMFS_VERSION);
296
297 // Calculate and set CVMFS_VERSION_NUMERIC
298 // Format: major * 10000 + minor * 100 + patch
299 // Example: 2.13.2 becomes 21302
300 ✗ const int version_numeric = CVMFS_VERSION_MAJOR * 10000
301 + CVMFS_VERSION_MINOR * 100 + CVMFS_VERSION_PATCH;
302 char version_numeric_str[16];
303 ✗ snprintf(version_numeric_str, sizeof(version_numeric_str), "%d",
304 version_numeric);
305 ✗ SetValue("CVMFS_VERSION_NUMERIC", version_numeric_str);
306 }
307
308 ✗ void OptionsManager::ParseDefault(const string &fqrn) {
309 ✗ if (taint_environment_) {
310 ✗ const int retval = setenv("CVMFS_FQRN", fqrn.c_str(), 1);
311 ✗ assert(retval == 0);
312 }
313
314 ✗ SetupGlobalEnvironmentParams();
315 ✗ protected_parameters_.clear();
316 ✗ ParsePath("/etc/cvmfs/default.conf", false);
317 vector<string> dist_defaults = FindFilesBySuffix("/etc/cvmfs/default.d",
318 ✗ ".conf");
319 ✗ for (unsigned i = 0; i < dist_defaults.size(); ++i) {
320 ✗ ParsePath(dist_defaults[i], false);
321 }
322 ✗ ProtectParameter("CVMFS_CONFIG_REPOSITORY");
323 ✗ string external_config_path;
324 ✗ if ((fqrn != "") && HasConfigRepository(fqrn, &external_config_path))
325 ✗ ParsePath(external_config_path + "default.conf", true);
326 ✗ ParsePath("/etc/cvmfs/default.local", false);
327
328 ✗ if (fqrn != "") {
329 ✗ string domain;
330 ✗ vector<string> tokens = SplitString(fqrn, '.');
331 ✗ assert(tokens.size() > 1);
332 ✗ tokens.erase(tokens.begin());
333 ✗ domain = JoinStrings(tokens, ".");
334
335 ✗ if (HasConfigRepository(fqrn, &external_config_path))
336 ✗ ParsePath(external_config_path + "domain.d/" + domain + ".conf", true);
337 ✗ ParsePath("/etc/cvmfs/domain.d/" + domain + ".conf", false);
338 ✗ ParsePath("/etc/cvmfs/domain.d/" + domain + ".local", false);
339
340 ✗ if (HasConfigRepository(fqrn, &external_config_path))
341 ✗ ParsePath(external_config_path + "config.d/" + fqrn + ".conf", true);
342 ✗ ParsePath("/etc/cvmfs/config.d/" + fqrn + ".conf", false);
343 ✗ ParsePath("/etc/cvmfs/config.d/" + fqrn + ".local", false);
344 }
345 }
346
347
348 26662 void OptionsManager::PopulateParameter(const string &param, ConfigValue val) {
349
1/2
✓ Branch 1 taken 26662 times.
✗ Branch 2 not taken.
26662 const map<string, string>::const_iterator iter = protected_parameters_.find(
350 26662 param);
351
5/6
✓ Branch 3 taken 61 times.
✓ Branch 4 taken 26601 times.
✓ Branch 7 taken 61 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 61 times.
✓ Branch 10 taken 26601 times.
26662 if ((iter != protected_parameters_.end()) && (iter->second != val.value)) {
352
1/3
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
122 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
353 "error in cvmfs configuration: attempt to change protected %s "
354 "from %s to %s",
355 61 param.c_str(), iter->second.c_str(), val.value.c_str());
356 61 return;
357 }
358
2/4
✓ Branch 1 taken 26601 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26601 times.
✗ Branch 5 not taken.
26601 ParseValue(param, &val);
359
2/4
✓ Branch 1 taken 26601 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26601 times.
✗ Branch 5 not taken.
26601 config_[param] = val;
360
1/2
✓ Branch 1 taken 26601 times.
✗ Branch 2 not taken.
26601 UpdateEnvironment(param, val);
361 }
362
363 26706 void OptionsManager::UpdateEnvironment(const string &param, ConfigValue val) {
364
2/2
✓ Branch 0 taken 24434 times.
✓ Branch 1 taken 2272 times.
26706 if (taint_environment_) {
365 24434 const int retval = setenv(param.c_str(), val.value.c_str(), 1);
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24434 times.
24434 assert(retval == 0);
367 }
368 26706 }
369
370 26601 void OptionsManager::ParseValue(std::string param, ConfigValue *val) {
371
1/2
✓ Branch 1 taken 26601 times.
✗ Branch 2 not taken.
26601 const string orig = val->value;
372
1/2
✓ Branch 1 taken 26601 times.
✗ Branch 2 not taken.
26601 const bool has_templ = opt_templ_mgr_->ParseString(&(val->value));
373
2/2
✓ Branch 0 taken 410 times.
✓ Branch 1 taken 26191 times.
26601 if (has_templ) {
374
2/4
✓ Branch 1 taken 410 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 410 times.
✗ Branch 5 not taken.
410 templatable_values_[param] = orig;
375 }
376 26601 }
377
378
379 61 void OptionsManager::ProtectParameter(const string &param) {
380 61 string value;
381 // We don't care about the result. If param does not yet exists, we lock it
382 // to the empty string.
383
1/2
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
61 (void)GetValue(param, &value);
384
2/4
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
61 protected_parameters_[param] = value;
385 61 }
386
387
388 61 void OptionsManager::ClearConfig() { config_.clear(); }
389
390
391 15895 bool OptionsManager::IsDefined(const std::string &key) {
392
1/2
✓ Branch 1 taken 15895 times.
✗ Branch 2 not taken.
15895 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
393 15895 return iter != config_.end();
394 }
395
396
397 194373 bool OptionsManager::GetValue(const string &key, string *value) const {
398
1/2
✓ Branch 1 taken 194373 times.
✗ Branch 2 not taken.
194373 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
399
2/2
✓ Branch 2 taken 47537 times.
✓ Branch 3 taken 146836 times.
194373 if (iter != config_.end()) {
400
1/2
✓ Branch 2 taken 47537 times.
✗ Branch 3 not taken.
47537 *value = iter->second.value;
401 47537 return true;
402 }
403
1/2
✓ Branch 1 taken 146836 times.
✗ Branch 2 not taken.
146836 *value = "";
404 146836 return false;
405 }
406
407
408 126 std::string OptionsManager::GetValueOrDie(const string &key) {
409 126 std::string value;
410
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 const bool retval = GetValue(key, &value);
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (!retval) {
412 ✗ PANIC(kLogStderr | kLogDebug, "%s configuration parameter missing",
413 key.c_str());
414 }
415 126 return value;
416 }
417
418
419 19500 bool OptionsManager::GetSource(const string &key, string *value) {
420
1/2
✓ Branch 1 taken 19500 times.
✗ Branch 2 not taken.
19500 const map<string, ConfigValue>::const_iterator iter = config_.find(key);
421
1/2
✓ Branch 3 taken 19500 times.
✗ Branch 4 not taken.
19500 if (iter != config_.end()) {
422
1/2
✓ Branch 2 taken 19500 times.
✗ Branch 3 not taken.
19500 *value = iter->second.source;
423 19500 return true;
424 }
425 ✗ *value = "";
426 ✗ return false;
427 }
428
429
430 4139 bool OptionsManager::IsOn(const std::string &param_value) const {
431
1/2
✓ Branch 1 taken 4139 times.
✗ Branch 2 not taken.
4139 const string uppercase = ToUpper(param_value);
432
2/4
✓ Branch 2 taken 3787 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3787 times.
✗ Branch 6 not taken.
7926 return ((uppercase == "YES") || (uppercase == "ON") || (uppercase == "1")
433
3/4
✓ Branch 0 taken 3787 times.
✓ Branch 1 taken 352 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3787 times.
12065 || (uppercase == "TRUE"));
434 4139 }
435
436
437 88 bool OptionsManager::IsOff(const std::string &param_value) const {
438
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 const string uppercase = ToUpper(param_value);
439
3/4
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 44 times.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
176 return ((uppercase == "NO") || (uppercase == "OFF") || (uppercase == "0")
440
2/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
264 || (uppercase == "FALSE"));
441 88 }
442
443
444 3063 vector<string> OptionsManager::GetAllKeys() {
445 3063 vector<string> result;
446 3063 for (map<string, ConfigValue>::const_iterator i = config_.begin(),
447 3063 iEnd = config_.end();
448
2/2
✓ Branch 1 taken 20297 times.
✓ Branch 2 taken 3063 times.
23360 i != iEnd;
449 20297 ++i) {
450
1/2
✓ Branch 2 taken 20297 times.
✗ Branch 3 not taken.
20297 result.push_back(i->first);
451 }
452 3063 return result;
453 }
454
455
456 316 vector<string> OptionsManager::GetEnvironmentSubset(const string &key_prefix,
457 bool strip_prefix) {
458 316 vector<string> result;
459 316 for (map<string, ConfigValue>::const_iterator i = config_.begin(),
460 316 iEnd = config_.end();
461
2/2
✓ Branch 1 taken 4148 times.
✓ Branch 2 taken 316 times.
4464 i != iEnd;
462 4148 ++i) {
463 4148 const bool ignore_prefix = false;
464
3/4
✓ Branch 2 taken 4148 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 427 times.
✓ Branch 5 taken 3721 times.
4148 if (HasPrefix(i->first, key_prefix, ignore_prefix)) {
465 const string output_key = strip_prefix
466 61 ? i->first.substr(key_prefix.length())
467
4/6
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 366 times.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 366 times.
✗ Branch 9 not taken.
488 : i->first;
468
3/6
✓ Branch 2 taken 427 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 427 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 427 times.
✗ Branch 9 not taken.
427 result.push_back(output_key + "=" + i->second.value);
469 427 }
470 }
471 316 return result;
472 }
473
474
475 2941 string OptionsManager::Dump() {
476 2941 string result;
477
1/2
✓ Branch 1 taken 2941 times.
✗ Branch 2 not taken.
2941 vector<string> keys = GetAllKeys();
478
2/2
✓ Branch 1 taken 19260 times.
✓ Branch 2 taken 2941 times.
22201 for (unsigned i = 0, l = keys.size(); i < l; ++i) {
479 bool retval;
480 19260 string value;
481 19260 string source;
482
483
1/2
✓ Branch 2 taken 19260 times.
✗ Branch 3 not taken.
19260 retval = GetValue(keys[i], &value);
484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19260 times.
19260 assert(retval);
485
1/2
✓ Branch 2 taken 19260 times.
✗ Branch 3 not taken.
19260 retval = GetSource(keys[i], &source);
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19260 times.
19260 assert(retval);
487
5/10
✓ Branch 1 taken 19260 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 19260 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 19260 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 19260 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 19260 times.
✗ Branch 15 not taken.
38520 result += keys[i] + "=" + EscapeShell(value) + " # from " + source
488
2/4
✓ Branch 1 taken 19260 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19260 times.
✗ Branch 5 not taken.
19260 + "\n";
489 19260 }
490 5882 return result;
491 2941 }
492
493 ✗ void OptionsManager::SetValueFromTalk(const string &key, const string &value) {
494 ✗ ConfigValue config_value;
495 ✗ config_value.source = "cvmfs_talk";
496 ✗ config_value.value = value;
497 ✗ PopulateParameter(key, config_value);
498 }
499
500 15053 void OptionsManager::SetValue(const string &key, const string &value) {
501 15053 ConfigValue config_value;
502
1/2
✓ Branch 1 taken 15053 times.
✗ Branch 2 not taken.
15053 config_value.source = "@INTERNAL@";
503
1/2
✓ Branch 1 taken 15053 times.
✗ Branch 2 not taken.
15053 config_value.value = value;
504
2/4
✓ Branch 1 taken 15053 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15053 times.
✗ Branch 5 not taken.
15053 PopulateParameter(key, config_value);
505 15053 }
506
507
508 837 void OptionsManager::UnsetValue(const string &key) {
509 837 protected_parameters_.erase(key);
510 837 config_.erase(key);
511
2/2
✓ Branch 0 taken 776 times.
✓ Branch 1 taken 61 times.
837 if (taint_environment_)
512 776 unsetenv(key.c_str());
513 837 }
514
515 const char *DefaultOptionsTemplateManager ::kTemplateIdentFqrn = "fqrn";
516
517 const char *DefaultOptionsTemplateManager ::kTemplateIdentOrg = "org";
518
519 844 DefaultOptionsTemplateManager::DefaultOptionsTemplateManager(std::string fqrn) {
520
3/6
✓ Branch 1 taken 844 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 844 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 844 times.
✗ Branch 9 not taken.
844 SetTemplate(kTemplateIdentFqrn, fqrn);
521
1/2
✓ Branch 1 taken 844 times.
✗ Branch 2 not taken.
844 vector<string> fqrn_parts = SplitString(fqrn, '.');
522
3/6
✓ Branch 2 taken 844 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 844 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 844 times.
✗ Branch 10 not taken.
844 SetTemplate(kTemplateIdentOrg, fqrn_parts[0]);
523 844 }
524
525 1853 void OptionsTemplateManager::SetTemplate(std::string name, std::string val) {
526 1853 templates_[name] = val;
527 1853 }
528
529 1681 std::string OptionsTemplateManager::GetTemplate(std::string name) {
530
2/2
✓ Branch 1 taken 374 times.
✓ Branch 2 taken 1307 times.
1681 if (templates_.count(name)) {
531 374 return templates_[name];
532 } else {
533
2/4
✓ Branch 1 taken 1307 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1307 times.
✗ Branch 5 not taken.
1307 std::string var_name = "@" + name + "@";
534
1/2
✓ Branch 2 taken 1307 times.
✗ Branch 3 not taken.
1307 LogCvmfs(kLogCvmfs, kLogDebug, "Undeclared variable: %s", var_name.c_str());
535 1307 return var_name;
536 1307 }
537 }
538
539 26810 bool OptionsTemplateManager::ParseString(std::string *input) {
540 26810 std::string result;
541
1/2
✓ Branch 1 taken 26810 times.
✗ Branch 2 not taken.
26810 std::string in = *input;
542 26810 bool has_vars = false;
543 26810 int mode = 0;
544 26810 std::string stock;
545
2/2
✓ Branch 1 taken 650119 times.
✓ Branch 2 taken 26810 times.
676929 for (std::string::size_type i = 0; i < in.size(); i++) {
546
2/3
✓ Branch 0 taken 640882 times.
✓ Branch 1 taken 9237 times.
✗ Branch 2 not taken.
650119 switch (mode) {
547 640882 case 0:
548
3/4
✓ Branch 1 taken 640882 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1917 times.
✓ Branch 4 taken 638965 times.
640882 if (in[i] == '@') {
549 1917 mode = 1;
550 } else {
551
2/4
✓ Branch 1 taken 638965 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 638965 times.
✗ Branch 5 not taken.
638965 result += in[i];
552 }
553 640882 break;
554 9237 case 1:
555
3/4
✓ Branch 1 taken 9237 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1499 times.
✓ Branch 4 taken 7738 times.
9237 if (in[i] == '@') {
556 1499 mode = 0;
557
3/6
✓ Branch 1 taken 1499 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1499 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1499 times.
✗ Branch 8 not taken.
1499 result += GetTemplate(stock);
558
1/2
✓ Branch 1 taken 1499 times.
✗ Branch 2 not taken.
1499 stock = "";
559 1499 has_vars = true;
560 } else {
561
2/4
✓ Branch 1 taken 7738 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7738 times.
✗ Branch 5 not taken.
7738 stock += in[i];
562 }
563 9237 break;
564 }
565 }
566
2/2
✓ Branch 0 taken 418 times.
✓ Branch 1 taken 26392 times.
26810 if (mode == 1) {
567
2/4
✓ Branch 1 taken 418 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 418 times.
✗ Branch 5 not taken.
418 result += "@" + stock;
568 }
569
1/2
✓ Branch 1 taken 26810 times.
✗ Branch 2 not taken.
26810 *input = result;
570 26810 return has_vars;
571 26810 }
572
573 182 bool OptionsTemplateManager::HasTemplate(std::string name) {
574 182 return templates_.count(name);
575 }
576
577 #ifdef CVMFS_NAMESPACE_GUARD
578 } // namespace CVMFS_NAMESPACE_GUARD
579 #endif
580