entity-manager: Search sysconfdir for configurations

Make it easier to iteratively develop configurations in-place with a
read-only /usr.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: Id0853b579a61394cb2b6ef0a3858ba01e5cb2893
diff --git a/include/Utils.hpp b/include/Utils.hpp
index 7b50036..eb8b8f1 100644
--- a/include/Utils.hpp
+++ b/include/Utils.hpp
@@ -62,6 +62,9 @@
 bool findFiles(const std::filesystem::path& dirPath,
                const std::string& matchString,
                std::vector<std::filesystem::path>& foundPaths);
+bool findFiles(const std::vector<std::filesystem::path>&& dirPaths,
+               const std::string& matchString,
+               std::vector<std::filesystem::path>& foundPaths);
 
 bool getI2cDevicePaths(
     const std::filesystem::path& dirPath,
diff --git a/meson.build b/meson.build
index 16d86c5..bb5da8c 100644
--- a/meson.build
+++ b/meson.build
@@ -60,6 +60,11 @@
     get_option('datadir'),
     meson.project_name(),
 )
+sysconfdir = join_paths(
+    get_option('prefix'),
+    get_option('sysconfdir'),
+    meson.project_name(),
+)
 threads = dependency('threads')
 if cpp.has_header('valijson/validator.hpp')
     valijson = declare_dependency()
diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
index a46806a..d327f2b 100644
--- a/src/EntityManager.cpp
+++ b/src/EntityManager.cpp
@@ -42,6 +42,7 @@
 #include <map>
 #include <regex>
 #include <variant>
+constexpr const char* hostConfigurationDirectory = SYSCONF_DIR "configurations";
 constexpr const char* configurationDirectory = PACKAGE_DIR "configurations";
 constexpr const char* schemaDirectory = PACKAGE_DIR "configurations/schemas";
 constexpr const char* tempConfigDir = "/tmp/configuration/";
@@ -775,8 +776,10 @@
 {
     // find configuration files
     std::vector<std::filesystem::path> jsonPaths;
-    if (!findFiles(std::filesystem::path(configurationDirectory), R"(.*\.json)",
-                   jsonPaths))
+    if (!findFiles(
+            std::vector<std::filesystem::path>{configurationDirectory,
+                                               hostConfigurationDirectory},
+            R"(.*\.json)", jsonPaths))
     {
         std::cerr << "Unable to find any configuration files in "
                   << configurationDirectory << "\n";
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
index c774b65..8159f84 100644
--- a/src/FruDevice.cpp
+++ b/src/FruDevice.cpp
@@ -41,6 +41,7 @@
 #include <iomanip>
 #include <iostream>
 #include <limits>
+#include <map>
 #include <regex>
 #include <set>
 #include <sstream>
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 48c600a..489d47a 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -34,6 +34,7 @@
 
 #include <filesystem>
 #include <fstream>
+#include <map>
 #include <regex>
 
 constexpr const char* templateChar = "$";
@@ -63,6 +64,36 @@
     return true;
 }
 
+bool findFiles(const std::vector<fs::path>&& dirPaths,
+               const std::string& matchString,
+               std::vector<fs::path>& foundPaths)
+{
+    std::map<fs::path, fs::path> paths;
+    std::regex search(matchString);
+    std::smatch match;
+    for (const auto& dirPath : dirPaths)
+    {
+        if (!fs::exists(dirPath))
+            continue;
+
+        for (const auto& p : fs::directory_iterator(dirPath))
+        {
+            std::string path = p.path().string();
+            if (std::regex_search(path, match, search))
+            {
+                paths[p.path().filename()] = p.path();
+            }
+        }
+    }
+
+    for (const auto& [key, value] : paths)
+    {
+        foundPaths.emplace_back(value);
+    }
+
+    return !foundPaths.empty();
+}
+
 bool getI2cDevicePaths(const fs::path& dirPath,
                        boost::container::flat_map<size_t, fs::path>& busPaths)
 {
diff --git a/src/meson.build b/src/meson.build
index 5add400..d1112cc 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,4 +1,5 @@
 cpp_args = boost_args + ['-DPACKAGE_DIR="' + packagedir + '/"']
+cpp_args += ['-DSYSCONF_DIR="' + sysconfdir + '/"' ]
 
 executable(
     'entity-manager',