* loads the contents of a file into a std::stringstream document. If the file has a '#include file' * directive, that 'file' is read into the document beginning at the point where the * '#include' was found. This allows the 'strategy' and 'hosts' yaml files to be separate. The * 'strategy' yaml file would then normally have the '#include hosts.yml' in it's beginning. */
| 190 | * 'strategy' yaml file would then normally have the '#include hosts.yml' in it's beginning. |
| 191 | */ |
| 192 | void |
| 193 | NextHopStrategyFactory::loadConfigFile(const std::string &fileName, std::stringstream &doc, |
| 194 | std::unordered_set<std::string> &include_once) |
| 195 | { |
| 196 | const char *sep = " \t"; |
| 197 | char *tok, *last; |
| 198 | struct stat buf; |
| 199 | std::string line; |
| 200 | |
| 201 | if (stat(fileName.c_str(), &buf) == -1) { |
| 202 | std::string err_msg = strerror(errno); |
| 203 | throw std::invalid_argument("Unable to stat '" + fileName + "': " + err_msg); |
| 204 | } |
| 205 | |
| 206 | // if fileName is a directory, concatenate all '.yaml' files alphanumerically |
| 207 | // into a single document stream. No #include is supported. |
| 208 | if (S_ISDIR(buf.st_mode)) { |
| 209 | DIR *dir = nullptr; |
| 210 | struct dirent *dir_ent = nullptr; |
| 211 | std::vector<std::string_view> files; |
| 212 | |
| 213 | NH_Note("loading strategy YAML files from the directory %s", fileName.c_str()); |
| 214 | if ((dir = opendir(fileName.c_str())) == nullptr) { |
| 215 | std::string err_msg = strerror(errno); |
| 216 | throw std::invalid_argument("Unable to open the directory '" + fileName + "': " + err_msg); |
| 217 | } else { |
| 218 | while ((dir_ent = readdir(dir)) != nullptr) { |
| 219 | // filename should be greater that 6 characters to have a '.yaml' suffix. |
| 220 | if (strlen(dir_ent->d_name) < 6) { |
| 221 | continue; |
| 222 | } |
| 223 | std::string_view sv = dir_ent->d_name; |
| 224 | if (sv.find(".yaml", sv.size() - 5) == sv.size() - 5) { |
| 225 | files.push_back(sv); |
| 226 | } |
| 227 | } |
| 228 | // sort the files alphanumerically |
| 229 | std::sort(files.begin(), files.end(), |
| 230 | [](const std::string_view lhs, const std::string_view rhs) { return lhs.compare(rhs) < 0; }); |
| 231 | |
| 232 | for (auto &i : files) { |
| 233 | std::ifstream file(fileName + "/" + i.data()); |
| 234 | if (file.is_open()) { |
| 235 | while (std::getline(file, line)) { |
| 236 | if (line[0] == '#') { |
| 237 | // continue; |
| 238 | } |
| 239 | doc << line << "\n"; |
| 240 | } |
| 241 | file.close(); |
| 242 | } else { |
| 243 | throw std::invalid_argument("Unable to open and read '" + fileName + "/" + i.data() + "'"); |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | closedir(dir); |
| 248 | } else { |
| 249 | std::ifstream file(fileName); |