Directory: | cvmfs/ |
---|---|
File: | cvmfs/options.cc |
Date: | 2025-07-06 02:35:01 |
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 | 13749 | static string EscapeShell(const std::string &raw) { | |
35 |
2/2✓ Branch 1 taken 211130 times.
✓ Branch 2 taken 13648 times.
|
224778 | for (unsigned i = 0, l = raw.length(); i < l; ++i) { |
36 |
6/6✓ Branch 1 taken 186575 times.
✓ Branch 2 taken 24555 times.
✓ Branch 4 taken 165251 times.
✓ Branch 5 taken 21324 times.
✓ Branch 6 taken 101 times.
✓ Branch 7 taken 211029 times.
|
400936 | if (!(((raw[i] >= '0') && (raw[i] <= '9')) |
37 |
4/4✓ Branch 1 taken 164537 times.
✓ Branch 2 taken 25269 times.
✓ Branch 4 taken 148285 times.
✓ Branch 5 taken 16252 times.
|
189806 | || ((raw[i] >= 'A') && (raw[i] <= 'Z')) |
38 |
5/6✓ Branch 1 taken 138309 times.
✓ Branch 2 taken 35245 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 138309 times.
✓ Branch 7 taken 18915 times.
✓ Branch 8 taken 16330 times.
|
173554 | || ((raw[i] >= 'a') && (raw[i] <= 'z')) || (raw[i] == '/') |
39 |
6/6✓ Branch 1 taken 18272 times.
✓ Branch 2 taken 643 times.
✓ Branch 4 taken 10317 times.
✓ Branch 5 taken 7955 times.
✓ Branch 7 taken 341 times.
✓ Branch 8 taken 9976 times.
|
18915 | || (raw[i] == ':') || (raw[i] == '.') || (raw[i] == '_') |
40 |
3/4✓ Branch 1 taken 101 times.
✓ Branch 2 taken 240 times.
✓ Branch 4 taken 101 times.
✗ Branch 5 not taken.
|
341 | || (raw[i] == '-') || (raw[i] == ','))) { |
41 | 101 | goto escape_shell_quote; | |
42 | } | ||
43 | } | ||
44 |
1/2✓ Branch 1 taken 13648 times.
✗ Branch 2 not taken.
|
13648 | return raw; |
45 | |||
46 | 101 | escape_shell_quote: | |
47 |
1/2✓ Branch 2 taken 101 times.
✗ Branch 3 not taken.
|
202 | string result = "'"; |
48 |
2/2✓ Branch 1 taken 3421 times.
✓ Branch 2 taken 101 times.
|
3522 | for (unsigned i = 0, l = raw.length(); i < l; ++i) { |
49 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3421 times.
|
3421 | if (raw[i] == '\'') |
50 | ✗ | result += "\\"; | |
51 |
1/2✓ Branch 2 taken 3421 times.
✗ Branch 3 not taken.
|
3421 | result += raw[i]; |
52 | } | ||
53 |
1/2✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
|
101 | result += "'"; |
54 | 101 | return result; | |
55 | } | ||
56 | |||
57 | |||
58 | 8630 | string OptionsManager::TrimParameter(const string ¶meter) { | |
59 | 8630 | string result = Trim(parameter); | |
60 | // Strip "readonly" | ||
61 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8630 times.
|
8630 | if (result.find("readonly ") == 0) { |
62 | ✗ | result = result.substr(9); | |
63 | ✗ | result = Trim(result); | |
64 |
2/2✓ Branch 1 taken 330 times.
✓ Branch 2 taken 8300 times.
|
8630 | } else if (result.find("export ") == 0) { |
65 |
1/2✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
|
330 | result = result.substr(7); |
66 |
1/2✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
|
330 | result = Trim(result); |
67 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8300 times.
|
8300 | } else if (result.find("eval ") == 0) { |
68 | ✗ | result = result.substr(5); | |
69 | ✗ | result = Trim(result); | |
70 | } | ||
71 | 8630 | return result; | |
72 | } | ||
73 | |||
74 | 9620 | string OptionsManager::SanitizeParameterAssignment(string *line, | |
75 | vector<string> *tokens) { | ||
76 | 9620 | const size_t comment_idx = line->find("#"); | |
77 |
2/2✓ Branch 0 taken 660 times.
✓ Branch 1 taken 8960 times.
|
9620 | if (comment_idx != string::npos) |
78 |
1/2✓ Branch 1 taken 660 times.
✗ Branch 2 not taken.
|
660 | *line = line->substr(0, comment_idx); |
79 |
1/2✓ Branch 1 taken 9620 times.
✗ Branch 2 not taken.
|
9620 | *line = Trim(*line); |
80 |
2/2✓ Branch 1 taken 660 times.
✓ Branch 2 taken 8960 times.
|
9620 | if (line->empty()) |
81 |
1/2✓ Branch 2 taken 660 times.
✗ Branch 3 not taken.
|
660 | return ""; |
82 |
1/2✓ Branch 1 taken 8960 times.
✗ Branch 2 not taken.
|
8960 | *tokens = SplitString(*line, '='); |
83 |
2/2✓ Branch 1 taken 330 times.
✓ Branch 2 taken 8630 times.
|
8960 | if (tokens->size() < 2) |
84 |
1/2✓ Branch 2 taken 330 times.
✗ Branch 3 not taken.
|
330 | return ""; |
85 |
1/2✓ Branch 2 taken 8630 times.
✗ Branch 3 not taken.
|
8630 | string parameter = TrimParameter((*tokens)[0]); |
86 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8630 times.
|
8630 | if (parameter.find(" ") != string::npos) |
87 | ✗ | return ""; | |
88 | 8630 | return parameter; | |
89 | 8630 | } | |
90 | |||
91 | 391 | void OptionsManager::SwitchTemplateManager( | |
92 | OptionsTemplateManager *opt_templ_mgr_param) { | ||
93 |
1/2✓ Branch 0 taken 391 times.
✗ Branch 1 not taken.
|
391 | delete opt_templ_mgr_; |
94 |
1/2✓ Branch 0 taken 391 times.
✗ Branch 1 not taken.
|
391 | if (opt_templ_mgr_param != NULL) { |
95 | 391 | opt_templ_mgr_ = opt_templ_mgr_param; | |
96 | } else { | ||
97 | ✗ | opt_templ_mgr_ = new OptionsTemplateManager(); | |
98 | } | ||
99 | 391 | for (std::map<std::string, std::string>::iterator it = | |
100 | 391 | templatable_values_.begin(); | |
101 |
2/2✓ Branch 2 taken 137 times.
✓ Branch 3 taken 391 times.
|
528 | it != templatable_values_.end(); |
102 | 137 | it++) { | |
103 |
2/4✓ Branch 3 taken 137 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 137 times.
✗ Branch 7 not taken.
|
137 | config_[it->first].value = it->second; |
104 |
2/4✓ Branch 2 taken 137 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 137 times.
✗ Branch 6 not taken.
|
137 | opt_templ_mgr_->ParseString(&(config_[it->first].value)); |
105 |
2/4✓ Branch 2 taken 137 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 137 times.
✗ Branch 6 not taken.
|
137 | UpdateEnvironment(it->first, config_[it->first]); |
106 | } | ||
107 | 391 | } | |
108 | |||
109 | 63 | bool SimpleOptionsParser::TryParsePath(const string &config_file) { | |
110 |
1/2✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
|
63 | LogCvmfs(kLogCvmfs, kLogDebug, "Fast-parsing config file %s", |
111 | config_file.c_str()); | ||
112 | 63 | string line; | |
113 |
1/2✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
|
63 | FILE *fconfig = fopen(config_file.c_str(), "r"); |
114 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 56 times.
|
63 | if (fconfig == NULL) |
115 | 7 | return false; | |
116 | |||
117 | // Read line by line and extract parameters | ||
118 |
3/4✓ Branch 1 taken 868 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 812 times.
✓ Branch 4 taken 56 times.
|
868 | while (GetLineFile(fconfig, &line)) { |
119 | 812 | vector<string> tokens; | |
120 |
1/2✓ Branch 1 taken 812 times.
✗ Branch 2 not taken.
|
812 | const string parameter = SanitizeParameterAssignment(&line, &tokens); |
121 |
2/2✓ Branch 1 taken 210 times.
✓ Branch 2 taken 602 times.
|
812 | if (parameter.empty()) |
122 | 210 | continue; | |
123 | |||
124 | // Strip quotes from value | ||
125 |
1/2✓ Branch 3 taken 602 times.
✗ Branch 4 not taken.
|
602 | tokens.erase(tokens.begin()); |
126 |
3/6✓ Branch 2 taken 602 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 602 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 602 times.
✗ Branch 9 not taken.
|
1204 | string value = Trim(JoinStrings(tokens, "=")); |
127 | 602 | const unsigned value_length = value.length(); | |
128 |
2/2✓ Branch 0 taken 434 times.
✓ Branch 1 taken 168 times.
|
602 | if (value_length > 2) { |
129 |
3/7✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 42 times.
|
476 | if (((value[0] == '"') && ((value[value_length - 1] == '"'))) |
130 |
9/13✓ Branch 0 taken 42 times.
✓ Branch 1 taken 392 times.
✓ Branch 3 taken 392 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
✓ Branch 6 taken 350 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 42 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 84 times.
✓ Branch 13 taken 350 times.
|
476 | || ((value[0] == '\'') && ((value[value_length - 1] == '\'')))) { |
131 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
84 | value = value.substr(1, value_length - 2); |
132 | } | ||
133 | } | ||
134 | |||
135 | 602 | ConfigValue config_value; | |
136 |
1/2✓ Branch 1 taken 602 times.
✗ Branch 2 not taken.
|
602 | config_value.source = config_file; |
137 |
1/2✓ Branch 1 taken 602 times.
✗ Branch 2 not taken.
|
602 | config_value.value = value; |
138 |
2/4✓ Branch 1 taken 602 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 602 times.
✗ Branch 5 not taken.
|
602 | PopulateParameter(parameter, config_value); |
139 |
4/4✓ Branch 3 taken 602 times.
✓ Branch 4 taken 210 times.
✓ Branch 6 taken 602 times.
✓ Branch 7 taken 210 times.
|
1022 | } |
140 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | fclose(fconfig); |
141 | 56 | return true; | |
142 | 63 | } | |
143 | |||
144 | 792 | void BashOptionsManager::ParsePath(const string &config_file, | |
145 | const bool external) { | ||
146 |
1/2✓ Branch 2 taken 792 times.
✗ Branch 3 not taken.
|
792 | 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 | 792 | pid_t pid_child = 0; | |
151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 792 times.
|
792 | 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 792 times.
✗ Branch 2 not taken.
|
792 | const string config_path = GetParentPath(config_file); |
186 |
1/2✓ Branch 2 taken 792 times.
✗ Branch 3 not taken.
|
792 | FILE *fconfig = fopen(config_file.c_str(), "r"); |
187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 792 times.
|
792 | 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 48 times.
✓ Branch 1 taken 744 times.
|
792 | if (!fconfig) { |
195 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 48 times.
|
48 | 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 | 48 | return; | |
213 | } | ||
214 | |||
215 | int fd_stdin; | ||
216 | int fd_stdout; | ||
217 | int fd_stderr; | ||
218 |
1/2✓ Branch 1 taken 744 times.
✗ Branch 2 not taken.
|
744 | retval = Shell(&fd_stdin, &fd_stdout, &fd_stderr); |
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 744 times.
|
744 | assert(retval); |
220 | |||
221 | // Let the shell read the file | ||
222 | 1488 | string line; | |
223 |
1/2✓ Branch 2 taken 744 times.
✗ Branch 3 not taken.
|
1488 | const string newline = "\n"; |
224 |
5/15✗ Branch 1 not taken.
✓ Branch 2 taken 744 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 744 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 744 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 744 times.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 744 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1488 | const string cd = "cd \"" + ((config_path == "") ? "/" : config_path) + "\"" |
225 |
1/2✓ Branch 1 taken 744 times.
✗ Branch 2 not taken.
|
1488 | + newline; |
226 |
1/2✓ Branch 3 taken 744 times.
✗ Branch 4 not taken.
|
744 | WritePipe(fd_stdin, cd.data(), cd.length()); |
227 |
3/4✓ Branch 1 taken 9552 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8808 times.
✓ Branch 4 taken 744 times.
|
9552 | while (GetLineFile(fconfig, &line)) { |
228 |
1/2✓ Branch 3 taken 8808 times.
✗ Branch 4 not taken.
|
8808 | WritePipe(fd_stdin, line.data(), line.length()); |
229 |
1/2✓ Branch 3 taken 8808 times.
✗ Branch 4 not taken.
|
8808 | WritePipe(fd_stdin, newline.data(), newline.length()); |
230 | } | ||
231 |
1/2✓ Branch 1 taken 744 times.
✗ Branch 2 not taken.
|
744 | rewind(fconfig); |
232 | |||
233 | // Read line by line and extract parameters | ||
234 |
3/4✓ Branch 1 taken 9552 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8808 times.
✓ Branch 4 taken 744 times.
|
9552 | while (GetLineFile(fconfig, &line)) { |
235 | 8808 | vector<string> tokens; | |
236 |
1/2✓ Branch 1 taken 8808 times.
✗ Branch 2 not taken.
|
8808 | const string parameter = SanitizeParameterAssignment(&line, &tokens); |
237 |
2/2✓ Branch 1 taken 1440 times.
✓ Branch 2 taken 7368 times.
|
8808 | if (parameter.empty()) |
238 | 1440 | continue; | |
239 | |||
240 | 7368 | ConfigValue value; | |
241 |
1/2✓ Branch 1 taken 7368 times.
✗ Branch 2 not taken.
|
7368 | value.source = config_file; |
242 |
2/4✓ Branch 1 taken 7368 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7368 times.
✗ Branch 5 not taken.
|
7368 | const string sh_echo = "echo $" + parameter + "\n"; |
243 |
1/2✓ Branch 3 taken 7368 times.
✗ Branch 4 not taken.
|
7368 | WritePipe(fd_stdin, sh_echo.data(), sh_echo.length()); |
244 |
1/2✓ Branch 1 taken 7368 times.
✗ Branch 2 not taken.
|
7368 | GetLineFd(fd_stdout, &value.value); |
245 |
2/4✓ Branch 1 taken 7368 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7368 times.
✗ Branch 5 not taken.
|
7368 | PopulateParameter(parameter, value); |
246 |
4/4✓ Branch 3 taken 7368 times.
✓ Branch 4 taken 1440 times.
✓ Branch 6 taken 7368 times.
✓ Branch 7 taken 1440 times.
|
10248 | } |
247 | |||
248 |
1/2✓ Branch 1 taken 744 times.
✗ Branch 2 not taken.
|
744 | close(fd_stderr); |
249 |
1/2✓ Branch 1 taken 744 times.
✗ Branch 2 not taken.
|
744 | close(fd_stdout); |
250 |
1/2✓ Branch 1 taken 744 times.
✗ Branch 2 not taken.
|
744 | close(fd_stdin); |
251 |
1/2✓ Branch 1 taken 744 times.
✗ Branch 2 not taken.
|
744 | fclose(fconfig); |
252 | } | ||
253 | |||
254 | |||
255 | 1098 | bool OptionsManager::HasConfigRepository(const string &fqrn, | |
256 | string *config_path) { | ||
257 | 1098 | string cvmfs_mount_dir; | |
258 |
3/6✓ Branch 2 taken 1098 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1098 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1098 times.
|
1098 | if (!GetValue("CVMFS_MOUNT_DIR", &cvmfs_mount_dir)) { |
259 | ✗ | LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "CVMFS_MOUNT_DIR missing"); | |
260 | ✗ | return false; | |
261 | } | ||
262 | |||
263 | 1098 | string config_repository; | |
264 |
4/6✓ Branch 2 taken 1098 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1098 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 90 times.
✓ Branch 10 taken 1008 times.
|
1098 | if (GetValue("CVMFS_CONFIG_REPOSITORY", &config_repository)) { |
265 |
3/6✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 90 times.
|
90 | if (config_repository.empty() || (config_repository == fqrn)) |
266 | ✗ | return false; | |
267 |
1/2✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
|
90 | const sanitizer::RepositorySanitizer repository_sanitizer; |
268 |
2/4✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 90 times.
|
90 | 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 90 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 90 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 90 times.
✗ Branch 8 not taken.
|
90 | *config_path = cvmfs_mount_dir + "/" + config_repository + "/etc/cvmfs/"; |
275 | 90 | return true; | |
276 | 90 | } | |
277 | 1008 | return false; | |
278 | 1098 | } | |
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 | 18695 | void OptionsManager::PopulateParameter(const string ¶m, ConfigValue val) { | |
321 |
1/2✓ Branch 1 taken 18695 times.
✗ Branch 2 not taken.
|
18695 | const map<string, string>::const_iterator iter = protected_parameters_.find( |
322 | 18695 | param); | |
323 |
5/6✓ Branch 3 taken 55 times.
✓ Branch 4 taken 18640 times.
✓ Branch 7 taken 55 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 55 times.
✓ Branch 10 taken 18640 times.
|
18695 | if ((iter != protected_parameters_.end()) && (iter->second != val.value)) { |
324 |
1/3✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
110 | LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, |
325 | "error in cvmfs configuration: attempt to change protected %s " | ||
326 | "from %s to %s", | ||
327 | 55 | param.c_str(), iter->second.c_str(), val.value.c_str()); | |
328 | 55 | return; | |
329 | } | ||
330 |
2/4✓ Branch 1 taken 18640 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18640 times.
✗ Branch 5 not taken.
|
18640 | ParseValue(param, &val); |
331 |
2/4✓ Branch 1 taken 18640 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18640 times.
✗ Branch 5 not taken.
|
18640 | config_[param] = val; |
332 |
1/2✓ Branch 1 taken 18640 times.
✗ Branch 2 not taken.
|
18640 | UpdateEnvironment(param, val); |
333 | } | ||
334 | |||
335 | 18777 | void OptionsManager::UpdateEnvironment(const string ¶m, ConfigValue val) { | |
336 |
2/2✓ Branch 0 taken 14443 times.
✓ Branch 1 taken 4334 times.
|
18777 | if (taint_environment_) { |
337 | 14443 | const int retval = setenv(param.c_str(), val.value.c_str(), 1); | |
338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14443 times.
|
14443 | assert(retval == 0); |
339 | } | ||
340 | 18777 | } | |
341 | |||
342 | 18640 | void OptionsManager::ParseValue(std::string param, ConfigValue *val) { | |
343 |
1/2✓ Branch 1 taken 18640 times.
✗ Branch 2 not taken.
|
18640 | const string orig = val->value; |
344 |
1/2✓ Branch 1 taken 18640 times.
✗ Branch 2 not taken.
|
18640 | const bool has_templ = opt_templ_mgr_->ParseString(&(val->value)); |
345 |
2/2✓ Branch 0 taken 412 times.
✓ Branch 1 taken 18228 times.
|
18640 | if (has_templ) { |
346 |
2/4✓ Branch 1 taken 412 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 412 times.
✗ Branch 5 not taken.
|
412 | templatable_values_[param] = orig; |
347 | } | ||
348 | 18640 | } | |
349 | |||
350 | |||
351 | 55 | void OptionsManager::ProtectParameter(const string ¶m) { | |
352 | 55 | string value; | |
353 | // We don't care about the result. If param does not yet exists, we lock it | ||
354 | // to the empty string. | ||
355 |
1/2✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
|
55 | (void)GetValue(param, &value); |
356 |
2/4✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
|
55 | protected_parameters_[param] = value; |
357 | 55 | } | |
358 | |||
359 | |||
360 | 55 | void OptionsManager::ClearConfig() { config_.clear(); } | |
361 | |||
362 | |||
363 | 12852 | bool OptionsManager::IsDefined(const std::string &key) { | |
364 |
1/2✓ Branch 1 taken 12852 times.
✗ Branch 2 not taken.
|
12852 | const map<string, ConfigValue>::const_iterator iter = config_.find(key); |
365 | 12852 | return iter != config_.end(); | |
366 | } | ||
367 | |||
368 | |||
369 | 138014 | bool OptionsManager::GetValue(const string &key, string *value) const { | |
370 |
1/2✓ Branch 1 taken 138014 times.
✗ Branch 2 not taken.
|
138014 | const map<string, ConfigValue>::const_iterator iter = config_.find(key); |
371 |
2/2✓ Branch 2 taken 33626 times.
✓ Branch 3 taken 104388 times.
|
138014 | if (iter != config_.end()) { |
372 |
1/2✓ Branch 2 taken 33626 times.
✗ Branch 3 not taken.
|
33626 | *value = iter->second.value; |
373 | 33626 | return true; | |
374 | } | ||
375 |
1/2✓ Branch 1 taken 104388 times.
✗ Branch 2 not taken.
|
104388 | *value = ""; |
376 | 104388 | return false; | |
377 | } | ||
378 | |||
379 | |||
380 | 90 | std::string OptionsManager::GetValueOrDie(const string &key) { | |
381 | 90 | std::string value; | |
382 |
1/2✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
|
90 | const bool retval = GetValue(key, &value); |
383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (!retval) { |
384 | ✗ | PANIC(kLogStderr | kLogDebug, "%s configuration parameter missing", | |
385 | key.c_str()); | ||
386 | } | ||
387 | 90 | return value; | |
388 | } | ||
389 | |||
390 | |||
391 | 14079 | bool OptionsManager::GetSource(const string &key, string *value) { | |
392 |
1/2✓ Branch 1 taken 14079 times.
✗ Branch 2 not taken.
|
14079 | const map<string, ConfigValue>::const_iterator iter = config_.find(key); |
393 |
1/2✓ Branch 3 taken 14079 times.
✗ Branch 4 not taken.
|
14079 | if (iter != config_.end()) { |
394 |
1/2✓ Branch 2 taken 14079 times.
✗ Branch 3 not taken.
|
14079 | *value = iter->second.source; |
395 | 14079 | return true; | |
396 | } | ||
397 | ✗ | *value = ""; | |
398 | ✗ | return false; | |
399 | } | ||
400 | |||
401 | |||
402 | 2307 | bool OptionsManager::IsOn(const std::string ¶m_value) const { | |
403 |
1/2✓ Branch 1 taken 2307 times.
✗ Branch 2 not taken.
|
2307 | const string uppercase = ToUpper(param_value); |
404 |
2/4✓ Branch 2 taken 2067 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2067 times.
✗ Branch 6 not taken.
|
4374 | return ((uppercase == "YES") || (uppercase == "ON") || (uppercase == "1") |
405 |
3/4✓ Branch 0 taken 2067 times.
✓ Branch 1 taken 240 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2067 times.
|
6681 | || (uppercase == "TRUE")); |
406 | 2307 | } | |
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 | 2330 | vector<string> OptionsManager::GetAllKeys() { | |
417 | 2330 | vector<string> result; | |
418 | 2330 | for (map<string, ConfigValue>::const_iterator i = config_.begin(), | |
419 | 2330 | iEnd = config_.end(); | |
420 |
2/2✓ Branch 1 taken 14519 times.
✓ Branch 2 taken 2330 times.
|
16849 | i != iEnd; |
421 | 14519 | ++i) { | |
422 |
1/2✓ Branch 2 taken 14519 times.
✗ Branch 3 not taken.
|
14519 | result.push_back(i->first); |
423 | } | ||
424 | 2330 | return result; | |
425 | } | ||
426 | |||
427 | |||
428 | 376 | vector<string> OptionsManager::GetEnvironmentSubset(const string &key_prefix, | |
429 | bool strip_prefix) { | ||
430 | 376 | vector<string> result; | |
431 | 376 | for (map<string, ConfigValue>::const_iterator i = config_.begin(), | |
432 | 376 | iEnd = config_.end(); | |
433 |
2/2✓ Branch 1 taken 3080 times.
✓ Branch 2 taken 376 times.
|
3456 | i != iEnd; |
434 | 3080 | ++i) { | |
435 | 3080 | const bool ignore_prefix = false; | |
436 |
3/4✓ Branch 2 taken 3080 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 385 times.
✓ Branch 5 taken 2695 times.
|
3080 | if (HasPrefix(i->first, key_prefix, ignore_prefix)) { |
437 | const string output_key = strip_prefix | ||
438 | 55 | ? i->first.substr(key_prefix.length()) | |
439 |
4/6✓ Branch 0 taken 55 times.
✓ Branch 1 taken 330 times.
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 330 times.
✗ Branch 9 not taken.
|
440 | : i->first; |
440 |
3/6✓ Branch 2 taken 385 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 385 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 385 times.
✗ Branch 9 not taken.
|
385 | result.push_back(output_key + "=" + i->second.value); |
441 | 385 | } | |
442 | } | ||
443 | 376 | return result; | |
444 | } | ||
445 | |||
446 | |||
447 | 2220 | string OptionsManager::Dump() { | |
448 | 2220 | string result; | |
449 |
1/2✓ Branch 1 taken 2220 times.
✗ Branch 2 not taken.
|
2220 | vector<string> keys = GetAllKeys(); |
450 |
2/2✓ Branch 1 taken 13749 times.
✓ Branch 2 taken 2220 times.
|
15969 | for (unsigned i = 0, l = keys.size(); i < l; ++i) { |
451 | bool retval; | ||
452 | 13749 | string value; | |
453 | 13749 | string source; | |
454 | |||
455 |
1/2✓ Branch 2 taken 13749 times.
✗ Branch 3 not taken.
|
13749 | retval = GetValue(keys[i], &value); |
456 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13749 times.
|
13749 | assert(retval); |
457 |
1/2✓ Branch 2 taken 13749 times.
✗ Branch 3 not taken.
|
13749 | retval = GetSource(keys[i], &source); |
458 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13749 times.
|
13749 | assert(retval); |
459 |
5/10✓ Branch 1 taken 13749 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 13749 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 13749 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 13749 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 13749 times.
✗ Branch 15 not taken.
|
27498 | result += keys[i] + "=" + EscapeShell(value) + " # from " + source |
460 |
2/4✓ Branch 1 taken 13749 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13749 times.
✗ Branch 5 not taken.
|
13749 | + "\n"; |
461 | 13749 | } | |
462 | 4440 | return result; | |
463 | 2220 | } | |
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 | 10725 | void OptionsManager::SetValue(const string &key, const string &value) { | |
473 | 10725 | ConfigValue config_value; | |
474 |
1/2✓ Branch 1 taken 10725 times.
✗ Branch 2 not taken.
|
10725 | config_value.source = "@INTERNAL@"; |
475 |
1/2✓ Branch 1 taken 10725 times.
✗ Branch 2 not taken.
|
10725 | config_value.value = value; |
476 |
2/4✓ Branch 1 taken 10725 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10725 times.
✗ Branch 5 not taken.
|
10725 | PopulateParameter(key, config_value); |
477 | 10725 | } | |
478 | |||
479 | |||
480 | 590 | void OptionsManager::UnsetValue(const string &key) { | |
481 | 590 | protected_parameters_.erase(key); | |
482 | 590 | config_.erase(key); | |
483 |
2/2✓ Branch 0 taken 535 times.
✓ Branch 1 taken 55 times.
|
590 | if (taint_environment_) |
484 | 535 | unsetenv(key.c_str()); | |
485 | 590 | } | |
486 | |||
487 | const char *DefaultOptionsTemplateManager ::kTemplateIdentFqrn = "fqrn"; | ||
488 | |||
489 | const char *DefaultOptionsTemplateManager ::kTemplateIdentOrg = "org"; | ||
490 | |||
491 | 790 | DefaultOptionsTemplateManager::DefaultOptionsTemplateManager(std::string fqrn) { | |
492 |
3/6✓ Branch 1 taken 790 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 790 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 790 times.
✗ Branch 9 not taken.
|
790 | SetTemplate(kTemplateIdentFqrn, fqrn); |
493 |
1/2✓ Branch 1 taken 790 times.
✗ Branch 2 not taken.
|
790 | vector<string> fqrn_parts = SplitString(fqrn, '.'); |
494 |
3/6✓ Branch 2 taken 790 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 790 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 790 times.
✗ Branch 10 not taken.
|
790 | SetTemplate(kTemplateIdentOrg, fqrn_parts[0]); |
495 | 790 | } | |
496 | |||
497 | 1791 | void OptionsTemplateManager::SetTemplate(std::string name, std::string val) { | |
498 | 1791 | templates_[name] = val; | |
499 | 1791 | } | |
500 | |||
501 | 1787 | std::string OptionsTemplateManager::GetTemplate(std::string name) { | |
502 |
2/2✓ Branch 1 taken 504 times.
✓ Branch 2 taken 1283 times.
|
1787 | if (templates_.count(name)) { |
503 | 504 | return templates_[name]; | |
504 | } else { | ||
505 |
2/4✓ Branch 1 taken 1283 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1283 times.
✗ Branch 5 not taken.
|
1283 | std::string var_name = "@" + name + "@"; |
506 |
1/2✓ Branch 2 taken 1283 times.
✗ Branch 3 not taken.
|
1283 | LogCvmfs(kLogCvmfs, kLogDebug, "Undeclared variable: %s", var_name.c_str()); |
507 | 1283 | return var_name; | |
508 | 1283 | } | |
509 | } | ||
510 | |||
511 | 18933 | bool OptionsTemplateManager::ParseString(std::string *input) { | |
512 | 18933 | std::string result; | |
513 |
1/2✓ Branch 1 taken 18933 times.
✗ Branch 2 not taken.
|
18933 | std::string in = *input; |
514 | 18933 | bool has_vars = false; | |
515 | 18933 | int mode = 0; | |
516 | 18933 | std::string stock; | |
517 |
2/2✓ Branch 1 taken 469028 times.
✓ Branch 2 taken 18933 times.
|
487961 | for (std::string::size_type i = 0; i < in.size(); i++) { |
518 |
2/3✓ Branch 0 taken 459883 times.
✓ Branch 1 taken 9145 times.
✗ Branch 2 not taken.
|
469028 | switch (mode) { |
519 | 459883 | case 0: | |
520 |
3/4✓ Branch 1 taken 459883 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1922 times.
✓ Branch 4 taken 457961 times.
|
459883 | if (in[i] == '@') { |
521 | 1922 | mode = 1; | |
522 | } else { | ||
523 |
2/4✓ Branch 1 taken 457961 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 457961 times.
✗ Branch 5 not taken.
|
457961 | result += in[i]; |
524 | } | ||
525 | 459883 | break; | |
526 | 9145 | case 1: | |
527 |
3/4✓ Branch 1 taken 9145 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1514 times.
✓ Branch 4 taken 7631 times.
|
9145 | if (in[i] == '@') { |
528 | 1514 | mode = 0; | |
529 |
3/6✓ Branch 1 taken 1514 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1514 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1514 times.
✗ Branch 8 not taken.
|
1514 | result += GetTemplate(stock); |
530 |
1/2✓ Branch 1 taken 1514 times.
✗ Branch 2 not taken.
|
1514 | stock = ""; |
531 | 1514 | has_vars = true; | |
532 | } else { | ||
533 |
2/4✓ Branch 1 taken 7631 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7631 times.
✗ Branch 5 not taken.
|
7631 | stock += in[i]; |
534 | } | ||
535 | 9145 | break; | |
536 | } | ||
537 | } | ||
538 |
2/2✓ Branch 0 taken 408 times.
✓ Branch 1 taken 18525 times.
|
18933 | if (mode == 1) { |
539 |
2/4✓ Branch 1 taken 408 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 408 times.
✗ Branch 5 not taken.
|
408 | result += "@" + stock; |
540 | } | ||
541 |
1/2✓ Branch 1 taken 18933 times.
✗ Branch 2 not taken.
|
18933 | *input = result; |
542 | 18933 | return has_vars; | |
543 | 18933 | } | |
544 | |||
545 | 273 | bool OptionsTemplateManager::HasTemplate(std::string name) { | |
546 | 273 | return templates_.count(name); | |
547 | } | ||
548 | |||
549 | #ifdef CVMFS_NAMESPACE_GUARD | ||
550 | } // namespace CVMFS_NAMESPACE_GUARD | ||
551 | #endif | ||
552 |