1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright 2017 Intel Corporation 3 4 #include "utils.hpp" 5 6 #include <boost/algorithm/string/classification.hpp> 7 #include <boost/algorithm/string/find.hpp> 8 #include <boost/algorithm/string/replace.hpp> 9 #include <boost/algorithm/string/split.hpp> 10 #include <boost/container/flat_map.hpp> 11 #include <boost/lexical_cast.hpp> 12 #include <sdbusplus/bus/match.hpp> 13 14 #include <filesystem> 15 #include <iostream> 16 #include <map> 17 #include <regex> 18 19 namespace fs = std::filesystem; 20 21 bool findFiles(const fs::path& dirPath, const std::string& matchString, 22 std::vector<fs::path>& foundPaths) 23 { 24 if (!fs::exists(dirPath)) 25 { 26 return false; 27 } 28 29 std::regex search(matchString); 30 std::smatch match; 31 for (const auto& p : fs::directory_iterator(dirPath)) 32 { 33 std::string path = p.path().string(); 34 if (std::regex_search(path, match, search)) 35 { 36 foundPaths.emplace_back(p.path()); 37 } 38 } 39 return true; 40 } 41 42 bool findFiles(const std::vector<fs::path>&& dirPaths, 43 const std::string& matchString, 44 std::vector<fs::path>& foundPaths) 45 { 46 std::map<fs::path, fs::path> paths; 47 std::regex search(matchString); 48 std::smatch match; 49 for (const auto& dirPath : dirPaths) 50 { 51 if (!fs::exists(dirPath)) 52 { 53 continue; 54 } 55 56 for (const auto& p : fs::recursive_directory_iterator(dirPath)) 57 { 58 std::error_code ec; 59 if (p.is_directory(ec)) 60 { 61 continue; 62 } 63 64 std::string path = p.path().string(); 65 if (std::regex_search(path, match, search)) 66 { 67 paths[p.path().filename()] = p.path(); 68 } 69 } 70 } 71 72 for (const auto& [key, value] : paths) 73 { 74 foundPaths.emplace_back(value); 75 } 76 77 return !foundPaths.empty(); 78 } 79 80 bool getI2cDevicePaths(const fs::path& dirPath, 81 boost::container::flat_map<size_t, fs::path>& busPaths) 82 { 83 if (!fs::exists(dirPath)) 84 { 85 return false; 86 } 87 88 // Regex for matching the path 89 std::regex searchPath(std::string(R"(i2c-\d+$)")); 90 // Regex for matching the bus numbers 91 std::regex searchBus(std::string(R"(\w[^-]*$)")); 92 std::smatch matchPath; 93 std::smatch matchBus; 94 for (const auto& p : fs::directory_iterator(dirPath)) 95 { 96 std::string path = p.path().string(); 97 if (std::regex_search(path, matchPath, searchPath)) 98 { 99 if (std::regex_search(path, matchBus, searchBus)) 100 { 101 size_t bus = stoul(*matchBus.begin()); 102 busPaths.insert(std::pair<size_t, fs::path>(bus, p.path())); 103 } 104 } 105 } 106 107 return true; 108 } 109 110 /// \brief JSON/DBus matching Callable for std::variant (visitor) 111 /// 112 /// Default match JSON/DBus match implementation 113 /// \tparam T The concrete DBus value type from DBusValueVariant 114 template <typename T> 115 struct MatchProbe 116 { 117 /// \param probe the probe statement to match against 118 /// \param value the property value being matched to a probe 119 /// \return true if the dbusValue matched the probe otherwise false 120 static bool match(const nlohmann::json& probe, const T& value) 121 { 122 return probe == value; 123 } 124 }; 125 126 /// \brief JSON/DBus matching Callable for std::variant (visitor) 127 /// 128 /// std::string specialization of MatchProbe enabling regex matching 129 template <> 130 struct MatchProbe<std::string> 131 { 132 /// \param probe the probe statement to match against 133 /// \param value the string value being matched to a probe 134 /// \return true if the dbusValue matched the probe otherwise false 135 static bool match(const nlohmann::json& probe, const std::string& value) 136 { 137 if (probe.is_string()) 138 { 139 try 140 { 141 std::regex search(probe); 142 std::smatch regMatch; 143 return std::regex_search(value, regMatch, search); 144 } 145 catch (const std::regex_error&) 146 { 147 std::cerr << "Syntax error in regular expression: " << probe 148 << " will never match"; 149 } 150 } 151 152 // Skip calling nlohmann here, since it will never match a non-string 153 // to a std::string 154 return false; 155 } 156 }; 157 158 /// \brief Forwarding JSON/DBus matching Callable for std::variant (visitor) 159 /// 160 /// Forward calls to the correct template instantiation of MatchProbe 161 struct MatchProbeForwarder 162 { 163 explicit MatchProbeForwarder(const nlohmann::json& probe) : probeRef(probe) 164 {} 165 const nlohmann::json& probeRef; 166 167 template <typename T> 168 bool operator()(const T& dbusValue) const 169 { 170 return MatchProbe<T>::match(probeRef, dbusValue); 171 } 172 }; 173 174 bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue) 175 { 176 return std::visit(MatchProbeForwarder(probe), dbusValue); 177 } 178