|
28 | 28 | #include <mutex> |
29 | 29 | #include <unordered_map> |
30 | 30 | #include <unordered_set> |
| 31 | +#include <filesystem> |
31 | 32 | #include <fstream> |
32 | 33 | #include <cstring> |
33 | 34 |
|
@@ -176,85 +177,73 @@ createStrategiesFromFile(const char *file) |
176 | 177 | * 'strategy' yaml file would then normally have the '#include hosts.yml' in it's beginning. |
177 | 178 | */ |
178 | 179 | void |
179 | | -loadConfigFile(const std::string &fileName, std::stringstream &doc, std::unordered_set<std::string> &include_once) |
| 180 | +loadConfigFile(std::string const &pathnamein, std::stringstream &doc, std::unordered_set<std::string> &include_once) |
180 | 181 | { |
181 | | - const char *sep = " \t"; |
182 | | - char *tok, *last; |
183 | | - struct stat buf; |
184 | | - std::string line; |
| 182 | + constexpr std::string_view sep = " \t"; |
185 | 183 |
|
186 | | - if (stat(fileName.c_str(), &buf) == -1) { |
187 | | - std::string err_msg = strerror(errno); |
188 | | - throw std::invalid_argument("Unable to stat '" + fileName + "': " + err_msg); |
189 | | - } |
| 184 | + namespace fs = std::filesystem; |
| 185 | + fs::path const pathin(pathnamein); |
| 186 | + std::error_code ec; |
190 | 187 |
|
191 | 188 | // if fileName is a directory, concatenate all '.yaml' files alphanumerically |
192 | 189 | // into a single document stream. No #include is supported. |
193 | | - if (S_ISDIR(buf.st_mode)) { |
194 | | - DIR *dir = nullptr; |
195 | | - struct dirent *dir_ent = nullptr; |
196 | | - std::vector<std::string_view> files; |
197 | | - |
198 | | - TSDebug(PLUGIN_NAME, "loading strategy YAML files from the directory %s", fileName.c_str()); |
199 | | - if ((dir = opendir(fileName.c_str())) == nullptr) { |
200 | | - std::string err_msg = strerror(errno); |
201 | | - throw std::invalid_argument("Unable to open the directory '" + fileName + "': " + err_msg); |
202 | | - } else { |
203 | | - while ((dir_ent = readdir(dir)) != nullptr) { |
204 | | - // filename should be greater that 6 characters to have a '.yaml' suffix. |
205 | | - if (strlen(dir_ent->d_name) < 6) { |
206 | | - continue; |
207 | | - } |
208 | | - std::string_view sv = dir_ent->d_name; |
209 | | - if (sv.find(".yaml", sv.size() - 5) == sv.size() - 5) { |
210 | | - files.push_back(sv); |
| 190 | + if (fs::is_directory(pathin, ec)) { |
| 191 | + TSDebug(PLUGIN_NAME, "loading strategy YAML files from the directory %s", pathnamein.c_str()); |
| 192 | + |
| 193 | + std::vector<fs::path> subpaths; |
| 194 | + for (auto const &dirent : fs::directory_iterator(pathin)) { |
| 195 | + fs::path const subpath = dirent.path(); |
| 196 | + if (fs::is_regular_file(subpath, ec) && !fs::is_empty(subpath, ec)) { |
| 197 | + if (".yaml" == subpath.extension()) { |
| 198 | + subpaths.push_back(subpath); |
| 199 | + } else { |
| 200 | + TSDebug(PLUGIN_NAME, "Skipping dirent (not yaml): '%s'", subpath.c_str()); |
211 | 201 | } |
| 202 | + } else { |
| 203 | + TSDebug(PLUGIN_NAME, "Skipping dirent (not file/empty): '%s'", subpath.c_str()); |
212 | 204 | } |
213 | | - // sort the files alphanumerically |
214 | | - std::sort(files.begin(), files.end(), |
215 | | - [](const std::string_view lhs, const std::string_view rhs) { return lhs.compare(rhs) < 0; }); |
| 205 | + } |
216 | 206 |
|
217 | | - for (auto &f : files) { |
218 | | - std::ifstream file(fileName + "/" + f.data()); |
219 | | - if (file.is_open()) { |
220 | | - while (std::getline(file, line)) { |
221 | | - if (line[0] == '#') { |
222 | | - // continue; |
223 | | - } |
224 | | - doc << line << "\n"; |
225 | | - } |
226 | | - file.close(); |
227 | | - } else { |
228 | | - throw std::invalid_argument("Unable to open and read '" + fileName + "/" + f.data() + "'"); |
| 207 | + // sort the files alphanumerically |
| 208 | + std::sort(subpaths.begin(), subpaths.end()); |
| 209 | + |
| 210 | + for (fs::path const &fpath : subpaths) { |
| 211 | + std::ifstream ifs(fpath); |
| 212 | + if (ifs.is_open()) { |
| 213 | + std::string line; |
| 214 | + while (std::getline(ifs, line)) { |
| 215 | + doc << line << "\n"; |
229 | 216 | } |
| 217 | + ifs.close(); |
| 218 | + } else { |
| 219 | + throw std::invalid_argument("Unable to open and read: '" + fpath.string() + "'"); |
230 | 220 | } |
231 | 221 | } |
232 | | - closedir(dir); |
233 | | - } else { |
234 | | - std::ifstream file(fileName); |
235 | | - if (file.is_open()) { |
236 | | - while (std::getline(file, line)) { |
237 | | - if (line[0] == '#') { |
238 | | - tok = strtok_r(const_cast<char *>(line.c_str()), sep, &last); |
239 | | - if (tok != nullptr && strcmp(tok, "#include") == 0) { |
240 | | - std::string f = strtok_r(nullptr, sep, &last); |
241 | | - if (include_once.find(f) == include_once.end()) { |
242 | | - include_once.insert(f); |
243 | | - // try to load included file. |
244 | | - try { |
245 | | - loadConfigFile(f, doc, include_once); |
246 | | - } catch (std::exception &ex) { |
247 | | - throw std::invalid_argument("Unable to open included file '" + f + "' from '" + fileName + "'"); |
248 | | - } |
| 222 | + } else if (fs::is_regular_file(pathin, ec) && !fs::is_empty(pathin, ec)) { |
| 223 | + std::ifstream ifs(pathin); |
| 224 | + if (ifs.is_open()) { |
| 225 | + std::string line; |
| 226 | + while (std::getline(ifs, line)) { |
| 227 | + // include directive ?? |
| 228 | + if (0 == line.rfind("#include", 0)) { // starts_with |
| 229 | + std::string_view const sv(line.substr(line.find_first_of(sep))); |
| 230 | + std::string const pathinc(sv.substr(0, sv.find_first_of(sep))); |
| 231 | + if (include_once.end() == include_once.find(pathinc)) { |
| 232 | + TSDebug(PLUGIN_NAME, "Include directive: '%s'", pathinc.c_str()); |
| 233 | + include_once.insert(pathinc); |
| 234 | + try { |
| 235 | + loadConfigFile(pathinc, doc, include_once); |
| 236 | + } catch (std::exception &ex) { |
| 237 | + throw std::invalid_argument("Unable to open included file '" + pathinc + "' from '" + pathnamein + "'"); |
249 | 238 | } |
250 | 239 | } |
251 | 240 | } else { |
252 | 241 | doc << line << "\n"; |
253 | 242 | } |
254 | 243 | } |
255 | | - file.close(); |
| 244 | + ifs.close(); |
256 | 245 | } else { |
257 | | - throw std::invalid_argument("Unable to open and read '" + fileName + "'"); |
| 246 | + throw std::invalid_argument("Unable to open and read '" + pathnamein + "'"); |
258 | 247 | } |
259 | 248 | } |
260 | 249 | } |
0 commit comments