Directory: | cvmfs/ |
---|---|
File: | cvmfs/options.cc |
Date: | 2025-07-27 02:42:09 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 269 | 353 | 76.2% |
Branches: | 274 | 655 | 41.8% |
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 | 3382 | static string EscapeShell(const std::string &raw) { | |
35 |
2/2✓ Branch 1 taken 53252 times.
✓ Branch 2 taken 3360 times.
|
56612 | for (unsigned i = 0, l = raw.length(); i < l; ++i) { |
36 |
6/6✓ Branch 1 taken 46902 times.
✓ Branch 2 taken 6350 times.
✓ Branch 4 taken 41106 times.
✓ Branch 5 taken 5796 times.
✓ Branch 6 taken 22 times.
✓ Branch 7 taken 53230 times.
|
100708 | if (!(((raw[i] >= '0') && (raw[i] <= '9')) |
37 |
4/4✓ Branch 1 taken 40950 times.
✓ Branch 2 taken 6506 times.
✓ Branch 4 taken 36882 times.
✓ Branch 5 taken 4068 times.
|
47456 | || ((raw[i] >= 'A') && (raw[i] <= 'Z')) |
38 |
5/6✓ Branch 1 taken 34336 times.
✓ Branch 2 taken 9052 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 34336 times.
✓ Branch 7 taken 4737 times.
✓ Branch 8 taken 4315 times.
|
43388 | || ((raw[i] >= 'a') && (raw[i] <= 'z')) || (raw[i] == '/') |
39 |
6/6✓ Branch 1 taken 4600 times.
✓ Branch 2 taken 137 times.
✓ Branch 4 taken 2592 times.
✓ Branch 5 taken 2008 times.
✓ Branch 7 taken 46 times.
✓ Branch 8 taken 2546 times.
|
4737 | || (raw[i] == ':') || (raw[i] == '.') || (raw[i] == '_') |
40 |
3/4✓ Branch 1 taken 22 times.
✓ Branch 2 taken 24 times.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
|
46 | || (raw[i] == '-') || (raw[i] == ','))) { |
41 | 22 | goto escape_shell_quote; | |
42 | } | ||
43 | } | ||
44 |
1/2✓ Branch 1 taken 3360 times.
✗ Branch 2 not taken.
|
3360 | return raw; |
45 | |||
46 | 22 | escape_shell_quote: | |
47 |
1/2✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
44 | string result = "'"; |
48 |
2/2✓ Branch 1 taken 473 times.
✓ Branch 2 taken 22 times.
|
495 | for (unsigned i = 0, l = raw.length(); i < l; ++i) { |
49 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 473 times.
|
473 | if (raw[i] == '\'') |
50 | ✗ | result += "\\"; | |
51 |
1/2✓ Branch 2 taken 473 times.
✗ Branch 3 not taken.
|
473 | result += raw[i]; |
52 | } | ||
53 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | result += "'"; |
54 | 22 | return result; | |
55 | } | ||
56 | |||
57 | |||
58 | 5008 | string OptionsManager::TrimParameter(const string ¶meter) { | |
59 | 5008 | string result = Trim(parameter); | |
60 | // Strip "readonly" | ||
61 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5008 times.
|
5008 | 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 4708 times.
|
5008 | } 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 4708 times.
|
4708 | } else if (result.find("eval ") == 0) { |
68 | ✗ | result = result.substr(5); | |
69 | ✗ | result = Trim(result); | |
70 | } | ||
71 | 5008 | return result; | |
72 | } | ||
73 | |||
74 | 5908 | string OptionsManager::SanitizeParameterAssignment(string *line, | |
75 | vector<string> *tokens) { | ||
76 | 5908 | const size_t comment_idx = line->find("#"); | |
77 |
2/2✓ Branch 0 taken 600 times.
✓ Branch 1 taken 5308 times.
|
5908 | 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 5908 times.
✗ Branch 2 not taken.
|
5908 | *line = Trim(*line); |
80 |
2/2✓ Branch 1 taken 600 times.
✓ Branch 2 taken 5308 times.
|
5908 | if (line->empty()) |
81 |
1/2✓ Branch 2 taken 600 times.
✗ Branch 3 not taken.
|
600 | return ""; |
82 |
1/2✓ Branch 1 taken 5308 times.
✗ Branch 2 not taken.
|
5308 | *tokens = SplitString(*line, '='); |
83 |
2/2✓ Branch 1 taken 300 times.
✓ Branch 2 taken 5008 times.
|
5308 | if (tokens->size() < 2) |
84 |
1/2✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
|
300 | return ""; |
85 |
1/2✓ Branch 2 taken 5008 times.
✗ Branch 3 not taken.
|
5008 | string parameter = TrimParameter((*tokens)[0]); |
86 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5008 times.
|
5008 | if (parameter.find(" ") != string::npos) |
87 | ✗ | return ""; | |
88 | 5008 | return parameter; | |
89 | 5008 | } | |
90 | |||
91 | 180 | void OptionsManager::SwitchTemplateManager( | |
92 | OptionsTemplateManager *opt_templ_mgr_param) { | ||
93 |
1/2✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
|
180 | delete opt_templ_mgr_; |
94 |
1/2✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
|
180 | if (opt_templ_mgr_param != NULL) { |
95 | 180 | opt_templ_mgr_ = opt_templ_mgr_param; | |
96 | } else { | ||
97 | ✗ | opt_templ_mgr_ = new OptionsTemplateManager(); | |
98 | } | ||
99 | 180 | for (std::map<std::string, std::string>::iterator it = | |
100 | 180 | templatable_values_.begin(); | |
101 |
2/2✓ Branch 2 taken 82 times.
✓ Branch 3 taken 180 times.
|
262 | it != templatable_values_.end(); |
102 | 82 | it++) { | |
103 |
2/4✓ Branch 3 taken 82 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 82 times.
✗ Branch 7 not taken.
|
82 | config_[it->first].value = it->second; |
104 |
2/4✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 82 times.
✗ Branch 6 not taken.
|
82 | opt_templ_mgr_->ParseString(&(config_[it->first].value)); |
105 |
2/4✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 82 times.
✗ Branch 6 not taken.
|
82 | UpdateEnvironment(it->first, config_[it->first]); |
106 | } | ||
107 | 180 | } | |
108 | |||
109 | 441 | bool SimpleOptionsParser::TryParsePath(const string &config_file) { | |
110 |
1/2✓ Branch 2 taken 441 times.
✗ Branch 3 not taken.
|
441 | LogCvmfs(kLogCvmfs, kLogDebug, "Fast-parsing config file %s", |
111 | config_file.c_str()); | ||
112 | 441 | string line; | |
113 |
1/2✓ Branch 2 taken 441 times.
✗ Branch 3 not taken.
|
441 | FILE *fconfig = fopen(config_file.c_str(), "r"); |
114 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 392 times.
|
441 | if (fconfig == NULL) |
115 | 49 | return false; | |
116 | |||
117 | // Read line by line and extract parameters | ||
118 |
3/4✓ Branch 1 taken 6076 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5684 times.
✓ Branch 4 taken 392 times.
|
6076 | while (GetLineFile(fconfig, &line)) { |
119 | 5684 | vector<string> tokens; | |
120 |
1/2✓ Branch 1 taken 5684 times.
✗ Branch 2 not taken.
|
5684 | const string parameter = SanitizeParameterAssignment(&line, &tokens); |
121 |
2/2✓ Branch 1 taken 1470 times.
✓ Branch 2 taken 4214 times.
|
5684 | if (parameter.empty()) |
122 | 1470 | continue; | |
123 | |||
124 | // Strip quotes from value | ||
125 |
1/2✓ Branch 3 taken 4214 times.
✗ Branch 4 not taken.
|
4214 | tokens.erase(tokens.begin()); |
126 |
3/6✓ Branch 2 taken 4214 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4214 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4214 times.
✗ Branch 9 not taken.
|
8428 | string value = Trim(JoinStrings(tokens, "=")); |
127 | 4214 | const unsigned value_length = value.length(); | |
128 |
2/2✓ Branch 0 taken 3038 times.
✓ Branch 1 taken 1176 times.
|
4214 | if (value_length > 2) { |
129 |
3/7✓ Branch 1 taken 3038 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 294 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 294 times.
|
3332 | if (((value[0] == '"') && ((value[value_length - 1] == '"'))) |
130 |
9/13✓ Branch 0 taken 294 times.
✓ Branch 1 taken 2744 times.
✓ Branch 3 taken 2744 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 294 times.
✓ Branch 6 taken 2450 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 294 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 294 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 588 times.
✓ Branch 13 taken 2450 times.
|
3332 | || ((value[0] == '\'') && ((value[value_length - 1] == '\'')))) { |
131 |
1/2✓ Branch 1 taken 588 times.
✗ Branch 2 not taken.
|
588 | value = value.substr(1, value_length - 2); |
132 | } | ||
133 | } | ||
134 | |||
135 | 4214 | ConfigValue config_value; | |
136 |
1/2✓ Branch 1 taken 4214 times.
✗ Branch 2 not taken.
|
4214 | config_value.source = config_file; |
137 |
1/2✓ Branch 1 taken 4214 times.
✗ Branch 2 not taken.
|
4214 | config_value.value = value; |
138 |
2/4✓ Branch 1 taken 4214 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4214 times.
✗ Branch 5 not taken.
|
4214 | PopulateParameter(parameter, config_value); |
139 |
4/4✓ Branch 3 taken 4214 times.
✓ Branch 4 taken 1470 times.
✓ Branch 6 taken 4214 times.
✓ Branch 7 taken 1470 times.
|
7154 | } |
140 |
1/2✓ Branch 1 taken 392 times.
✗ Branch 2 not taken.
|
392 | fclose(fconfig); |
141 | 392 | return true; | |
142 | 441 | } | |
143 | |||
144 | 21 | void BashOptionsManager::ParsePath(const string &config_file, | |
145 | const bool external) { | ||
146 |
1/2✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | 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 | 21 | pid_t pid_child = 0; | |
151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | 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 21 times.
✗ Branch 2 not taken.
|
21 | const string config_path = GetParentPath(config_file); |
186 |
1/2✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | FILE *fconfig = fopen(config_file.c_str(), "r"); |
187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | 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 1 times.
✓ Branch 1 taken 20 times.
|
21 | if (!fconfig) { |
195 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
|
1 | 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 | 1 | return; | |
213 | } | ||
214 | |||
215 | int fd_stdin; | ||
216 | int fd_stdout; | ||
217 | int fd_stderr; | ||
218 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | retval = Shell(&fd_stdin, &fd_stdout, &fd_stderr); |
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | assert(retval); |
220 | |||
221 | // Let the shell read the file | ||
222 | 40 | string line; | |
223 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
40 | const string newline = "\n"; |
224 |
5/15✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 20 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 20 times.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 20 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
40 | const string cd = "cd \"" + ((config_path == "") ? "/" : config_path) + "\"" |
225 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | + newline; |
226 |
1/2✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
|
20 | WritePipe(fd_stdin, cd.data(), cd.length()); |
227 |
3/4✓ Branch 1 taken 244 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 224 times.
✓ Branch 4 taken 20 times.
|
244 | while (GetLineFile(fconfig, &line)) { |
228 |
1/2✓ Branch 3 taken 224 times.
✗ Branch 4 not taken.
|
224 | WritePipe(fd_stdin, line.data(), line.length()); |
229 |
1/2✓ Branch 3 taken 224 times.
✗ Branch 4 not taken.
|
224 | WritePipe(fd_stdin, newline.data(), newline.length()); |
230 | } | ||
231 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | rewind(fconfig); |
232 | |||
233 | // Read line by line and extract parameters | ||
234 |
3/4✓ Branch 1 taken 244 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 224 times.
✓ Branch 4 taken 20 times.
|
244 | while (GetLineFile(fconfig, &line)) { |
235 | 224 | vector<string> tokens; | |
236 |
1/2✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
|
224 | const string parameter = SanitizeParameterAssignment(&line, &tokens); |
237 |
2/2✓ Branch 1 taken 30 times.
✓ Branch 2 taken 194 times.
|
224 | if (parameter.empty()) |
238 | 30 | continue; | |
239 | |||
240 | 194 | ConfigValue value; | |
241 |
1/2✓ Branch 1 taken 194 times.
✗ Branch 2 not taken.
|
194 | value.source = config_file; |
242 |
2/4✓ Branch 1 taken 194 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 194 times.
✗ Branch 5 not taken.
|
194 | const string sh_echo = "echo $" + parameter + "\n"; |
243 |
1/2✓ Branch 3 taken 194 times.
✗ Branch 4 not taken.
|
194 | WritePipe(fd_stdin, sh_echo.data(), sh_echo.length()); |
244 |
1/2✓ Branch 1 taken 194 times.
✗ Branch 2 not taken.
|
194 | GetLineFd(fd_stdout, &value.value); |
245 |
2/4✓ Branch 1 taken 194 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 194 times.
✗ Branch 5 not taken.
|
194 | PopulateParameter(parameter, value); |
246 |
4/4✓ Branch 3 taken 194 times.
✓ Branch 4 taken 30 times.
✓ Branch 6 taken 194 times.
✓ Branch 7 taken 30 times.
|
254 | } |
247 | |||
248 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | close(fd_stderr); |
249 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | close(fd_stdout); |
250 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | close(fd_stdin); |
251 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | fclose(fconfig); |
252 | } | ||
253 | |||
254 | |||
255 | 442 | bool OptionsManager::HasConfigRepository(const string &fqrn, | |
256 | string *config_path) { | ||
257 | 442 | string cvmfs_mount_dir; | |
258 |
3/6✓ Branch 2 taken 442 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 442 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 442 times.
|
442 | if (!GetValue("CVMFS_MOUNT_DIR", &cvmfs_mount_dir)) { |
259 | ✗ | LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "CVMFS_MOUNT_DIR missing"); | |
260 | ✗ | return false; | |
261 | } | ||
262 | |||
263 | 442 | string config_repository; | |
264 |
4/6✓ Branch 2 taken 442 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 442 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 433 times.
|
442 | 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 | 433 | return false; | |
278 | 442 | } | |
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 | 8394 | void OptionsManager::PopulateParameter(const string ¶m, ConfigValue val) { | |
321 |
1/2✓ Branch 1 taken 8394 times.
✗ Branch 2 not taken.
|
8394 | const map<string, string>::const_iterator iter = protected_parameters_.find( |
322 | 8394 | param); | |
323 |
5/6✓ Branch 3 taken 50 times.
✓ Branch 4 taken 8344 times.
✓ Branch 7 taken 50 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 50 times.
✓ Branch 10 taken 8344 times.
|
8394 | if ((iter != protected_parameters_.end()) && (iter->second != val.value)) { |
324 |
1/3✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
100 | LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, |
325 | "error in cvmfs configuration: attempt to change protected %s " | ||
326 | "from %s to %s", | ||
327 | 50 | param.c_str(), iter->second.c_str(), val.value.c_str()); | |
328 | 50 | return; | |
329 | } | ||
330 |
2/4✓ Branch 1 taken 8344 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8344 times.
✗ Branch 5 not taken.
|
8344 | ParseValue(param, &val); |
331 |
2/4✓ Branch 1 taken 8344 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8344 times.
✗ Branch 5 not taken.
|
8344 | config_[param] = val; |
332 |
1/2✓ Branch 1 taken 8344 times.
✗ Branch 2 not taken.
|
8344 | UpdateEnvironment(param, val); |
333 | } | ||
334 | |||
335 | 8426 | void OptionsManager::UpdateEnvironment(const string ¶m, ConfigValue val) { | |
336 |
2/2✓ Branch 0 taken 6706 times.
✓ Branch 1 taken 1720 times.
|
8426 | if (taint_environment_) { |
337 | 6706 | const int retval = setenv(param.c_str(), val.value.c_str(), 1); | |
338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6706 times.
|
6706 | assert(retval == 0); |
339 | } | ||
340 | 8426 | } | |
341 | |||
342 | 8344 | void OptionsManager::ParseValue(std::string param, ConfigValue *val) { | |
343 |
1/2✓ Branch 1 taken 8344 times.
✗ Branch 2 not taken.
|
8344 | const string orig = val->value; |
344 |
1/2✓ Branch 1 taken 8344 times.
✗ Branch 2 not taken.
|
8344 | const bool has_templ = opt_templ_mgr_->ParseString(&(val->value)); |
345 |
2/2✓ Branch 0 taken 332 times.
✓ Branch 1 taken 8012 times.
|
8344 | if (has_templ) { |
346 |
2/4✓ Branch 1 taken 332 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 332 times.
✗ Branch 5 not taken.
|
332 | templatable_values_[param] = orig; |
347 | } | ||
348 | 8344 | } | |
349 | |||
350 | |||
351 | 50 | void OptionsManager::ProtectParameter(const string ¶m) { | |
352 | 50 | 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 50 times.
✗ Branch 2 not taken.
|
50 | (void)GetValue(param, &value); |
356 |
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; |
357 | 50 | } | |
358 | |||
359 | |||
360 | 50 | void OptionsManager::ClearConfig() { config_.clear(); } | |
361 | |||
362 | |||
363 | 4033 | bool OptionsManager::IsDefined(const std::string &key) { | |
364 |
1/2✓ Branch 1 taken 4033 times.
✗ Branch 2 not taken.
|
4033 | const map<string, ConfigValue>::const_iterator iter = config_.find(key); |
365 | 4033 | return iter != config_.end(); | |
366 | } | ||
367 | |||
368 | |||
369 | 41358 | bool OptionsManager::GetValue(const string &key, string *value) const { | |
370 |
1/2✓ Branch 1 taken 41358 times.
✗ Branch 2 not taken.
|
41358 | const map<string, ConfigValue>::const_iterator iter = config_.find(key); |
371 |
2/2✓ Branch 2 taken 8988 times.
✓ Branch 3 taken 32370 times.
|
41358 | if (iter != config_.end()) { |
372 |
1/2✓ Branch 2 taken 8988 times.
✗ Branch 3 not taken.
|
8988 | *value = iter->second.value; |
373 | 8988 | return true; | |
374 | } | ||
375 |
1/2✓ Branch 1 taken 32370 times.
✗ Branch 2 not taken.
|
32370 | *value = ""; |
376 | 32370 | return false; | |
377 | } | ||
378 | |||
379 | |||
380 | 9 | std::string OptionsManager::GetValueOrDie(const string &key) { | |
381 | 9 | std::string value; | |
382 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | const bool retval = GetValue(key, &value); |
383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (!retval) { |
384 | ✗ | PANIC(kLogStderr | kLogDebug, "%s configuration parameter missing", | |
385 | key.c_str()); | ||
386 | } | ||
387 | 9 | return value; | |
388 | } | ||
389 | |||
390 | |||
391 | 3682 | bool OptionsManager::GetSource(const string &key, string *value) { | |
392 |
1/2✓ Branch 1 taken 3682 times.
✗ Branch 2 not taken.
|
3682 | const map<string, ConfigValue>::const_iterator iter = config_.find(key); |
393 |
1/2✓ Branch 3 taken 3682 times.
✗ Branch 4 not taken.
|
3682 | if (iter != config_.end()) { |
394 |
1/2✓ Branch 2 taken 3682 times.
✗ Branch 3 not taken.
|
3682 | *value = iter->second.source; |
395 | 3682 | return true; | |
396 | } | ||
397 | ✗ | *value = ""; | |
398 | ✗ | return false; | |
399 | } | ||
400 | |||
401 | |||
402 | 705 | bool OptionsManager::IsOn(const std::string ¶m_value) const { | |
403 |
1/2✓ Branch 1 taken 705 times.
✗ Branch 2 not taken.
|
705 | const string uppercase = ToUpper(param_value); |
404 |
2/4✓ Branch 2 taken 681 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 681 times.
✗ Branch 6 not taken.
|
1386 | return ((uppercase == "YES") || (uppercase == "ON") || (uppercase == "1") |
405 |
3/4✓ Branch 0 taken 681 times.
✓ Branch 1 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 681 times.
|
2091 | || (uppercase == "TRUE")); |
406 | 705 | } | |
407 | |||
408 | |||
409 | ✗ | bool OptionsManager::IsOff(const std::string ¶m_value) const { | |
410 | ✗ | const string uppercase = ToUpper(param_value); | |
411 | ✗ | return ((uppercase == "NO") || (uppercase == "OFF") || (uppercase == "0") | |
412 | ✗ | || (uppercase == "FALSE")); | |
413 | } | ||
414 | |||
415 | |||
416 | 793 | vector<string> OptionsManager::GetAllKeys() { | |
417 | 793 | vector<string> result; | |
418 | 793 | for (map<string, ConfigValue>::const_iterator i = config_.begin(), | |
419 | 793 | iEnd = config_.end(); | |
420 |
2/2✓ Branch 1 taken 4082 times.
✓ Branch 2 taken 793 times.
|
4875 | i != iEnd; |
421 | 4082 | ++i) { | |
422 |
1/2✓ Branch 2 taken 4082 times.
✗ Branch 3 not taken.
|
4082 | result.push_back(i->first); |
423 | } | ||
424 | 793 | return result; | |
425 | } | ||
426 | |||
427 | |||
428 | 204 | vector<string> OptionsManager::GetEnvironmentSubset(const string &key_prefix, | |
429 | bool strip_prefix) { | ||
430 | 204 | vector<string> result; | |
431 | 204 | for (map<string, ConfigValue>::const_iterator i = config_.begin(), | |
432 | 204 | iEnd = config_.end(); | |
433 |
2/2✓ Branch 1 taken 2800 times.
✓ Branch 2 taken 204 times.
|
3004 | i != iEnd; |
434 | 2800 | ++i) { | |
435 | 2800 | const bool ignore_prefix = false; | |
436 |
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)) { |
437 | const string output_key = strip_prefix | ||
438 | 50 | ? i->first.substr(key_prefix.length()) | |
439 |
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; |
440 |
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); |
441 | 350 | } | |
442 | } | ||
443 | 204 | return result; | |
444 | } | ||
445 | |||
446 | |||
447 | 693 | string OptionsManager::Dump() { | |
448 | 693 | string result; | |
449 |
1/2✓ Branch 1 taken 693 times.
✗ Branch 2 not taken.
|
693 | vector<string> keys = GetAllKeys(); |
450 |
2/2✓ Branch 1 taken 3382 times.
✓ Branch 2 taken 693 times.
|
4075 | for (unsigned i = 0, l = keys.size(); i < l; ++i) { |
451 | bool retval; | ||
452 | 3382 | string value; | |
453 | 3382 | string source; | |
454 | |||
455 |
1/2✓ Branch 2 taken 3382 times.
✗ Branch 3 not taken.
|
3382 | retval = GetValue(keys[i], &value); |
456 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3382 times.
|
3382 | assert(retval); |
457 |
1/2✓ Branch 2 taken 3382 times.
✗ Branch 3 not taken.
|
3382 | retval = GetSource(keys[i], &source); |
458 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3382 times.
|
3382 | assert(retval); |
459 |
5/10✓ Branch 1 taken 3382 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3382 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3382 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 3382 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 3382 times.
✗ Branch 15 not taken.
|
6764 | result += keys[i] + "=" + EscapeShell(value) + " # from " + source |
460 |
2/4✓ Branch 1 taken 3382 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3382 times.
✗ Branch 5 not taken.
|
3382 | + "\n"; |
461 | 3382 | } | |
462 | 1386 | return result; | |
463 | 693 | } | |
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 | 3986 | void OptionsManager::SetValue(const string &key, const string &value) { | |
473 | 3986 | ConfigValue config_value; | |
474 |
1/2✓ Branch 1 taken 3986 times.
✗ Branch 2 not taken.
|
3986 | config_value.source = "@INTERNAL@"; |
475 |
1/2✓ Branch 1 taken 3986 times.
✗ Branch 2 not taken.
|
3986 | config_value.value = value; |
476 |
2/4✓ Branch 1 taken 3986 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3986 times.
✗ Branch 5 not taken.
|
3986 | PopulateParameter(key, config_value); |
477 | 3986 | } | |
478 | |||
479 | |||
480 | 213 | void OptionsManager::UnsetValue(const string &key) { | |
481 | 213 | protected_parameters_.erase(key); | |
482 | 213 | config_.erase(key); | |
483 |
2/2✓ Branch 0 taken 163 times.
✓ Branch 1 taken 50 times.
|
213 | if (taint_environment_) |
484 | 163 | unsetenv(key.c_str()); | |
485 | 213 | } | |
486 | |||
487 | const char *DefaultOptionsTemplateManager ::kTemplateIdentFqrn = "fqrn"; | ||
488 | |||
489 | const char *DefaultOptionsTemplateManager ::kTemplateIdentOrg = "org"; | ||
490 | |||
491 | 195 | DefaultOptionsTemplateManager::DefaultOptionsTemplateManager(std::string fqrn) { | |
492 |
3/6✓ Branch 1 taken 195 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 195 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 195 times.
✗ Branch 9 not taken.
|
195 | SetTemplate(kTemplateIdentFqrn, fqrn); |
493 |
1/2✓ Branch 1 taken 195 times.
✗ Branch 2 not taken.
|
195 | vector<string> fqrn_parts = SplitString(fqrn, '.'); |
494 |
3/6✓ Branch 2 taken 195 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 195 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 195 times.
✗ Branch 10 not taken.
|
195 | SetTemplate(kTemplateIdentOrg, fqrn_parts[0]); |
495 | 195 | } | |
496 | |||
497 | 452 | void OptionsTemplateManager::SetTemplate(std::string name, std::string val) { | |
498 | 452 | templates_[name] = val; | |
499 | 452 | } | |
500 | |||
501 | 1150 | std::string OptionsTemplateManager::GetTemplate(std::string name) { | |
502 |
2/2✓ Branch 1 taken 156 times.
✓ Branch 2 taken 994 times.
|
1150 | if (templates_.count(name)) { |
503 | 156 | return templates_[name]; | |
504 | } else { | ||
505 |
2/4✓ Branch 1 taken 994 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 994 times.
✗ Branch 5 not taken.
|
994 | std::string var_name = "@" + name + "@"; |
506 |
1/2✓ Branch 2 taken 994 times.
✗ Branch 3 not taken.
|
994 | LogCvmfs(kLogCvmfs, kLogDebug, "Undeclared variable: %s", var_name.c_str()); |
507 | 994 | return var_name; | |
508 | 994 | } | |
509 | } | ||
510 | |||
511 | 8438 | bool OptionsTemplateManager::ParseString(std::string *input) { | |
512 | 8438 | std::string result; | |
513 |
1/2✓ Branch 1 taken 8438 times.
✗ Branch 2 not taken.
|
8438 | std::string in = *input; |
514 | 8438 | bool has_vars = false; | |
515 | 8438 | int mode = 0; | |
516 | 8438 | std::string stock; | |
517 |
2/2✓ Branch 1 taken 110582 times.
✓ Branch 2 taken 8438 times.
|
119020 | for (std::string::size_type i = 0; i < in.size(); i++) { |
518 |
2/3✓ Branch 0 taken 103560 times.
✓ Branch 1 taken 7022 times.
✗ Branch 2 not taken.
|
110582 | switch (mode) { |
519 | 103560 | case 0: | |
520 |
3/4✓ Branch 1 taken 103560 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1435 times.
✓ Branch 4 taken 102125 times.
|
103560 | if (in[i] == '@') { |
521 | 1435 | mode = 1; | |
522 | } else { | ||
523 |
2/4✓ Branch 1 taken 102125 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 102125 times.
✗ Branch 5 not taken.
|
102125 | result += in[i]; |
524 | } | ||
525 | 103560 | break; | |
526 | 7022 | case 1: | |
527 |
3/4✓ Branch 1 taken 7022 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1129 times.
✓ Branch 4 taken 5893 times.
|
7022 | if (in[i] == '@') { |
528 | 1129 | mode = 0; | |
529 |
3/6✓ Branch 1 taken 1129 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1129 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1129 times.
✗ Branch 8 not taken.
|
1129 | result += GetTemplate(stock); |
530 |
1/2✓ Branch 1 taken 1129 times.
✗ Branch 2 not taken.
|
1129 | stock = ""; |
531 | 1129 | has_vars = true; | |
532 | } else { | ||
533 |
2/4✓ Branch 1 taken 5893 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5893 times.
✗ Branch 5 not taken.
|
5893 | stock += in[i]; |
534 | } | ||
535 | 7022 | break; | |
536 | } | ||
537 | } | ||
538 |
2/2✓ Branch 0 taken 306 times.
✓ Branch 1 taken 8132 times.
|
8438 | if (mode == 1) { |
539 |
2/4✓ Branch 1 taken 306 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 306 times.
✗ Branch 5 not taken.
|
306 | result += "@" + stock; |
540 | } | ||
541 |
1/2✓ Branch 1 taken 8438 times.
✗ Branch 2 not taken.
|
8438 | *input = result; |
542 | 8438 | return has_vars; | |
543 | 8438 | } | |
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 |