From 417c4ae87e6963ca86f308b31793ef96cc33c71a Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Wed, 5 Feb 2020 11:21:38 +0000 Subject: libcamera: ipa_manager: Allow recursive parsing Provide an optional means to recurse into subdirectories to search for IPA libraries. This allows IPAs contained within their own build directory to be found when loading from a non-installed build. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/libcamera/ipa_manager.cpp | 62 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 13 deletions(-) (limited to 'src/libcamera/ipa_manager.cpp') diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp index 90dd3003..de99a0bc 100644 --- a/src/libcamera/ipa_manager.cpp +++ b/src/libcamera/ipa_manager.cpp @@ -142,47 +142,83 @@ IPAManager *IPAManager::instance() } /** - * \brief Load IPA modules from a directory - * \param[in] libDir directory to search for IPA modules + * \brief Identify shared library objects within a directory + * \param[in] libDir The directory to search for shared objects + * \param[in] maxDepth The maximum depth of sub-directories to parse + * \param[out] files A vector of paths to shared object library files * - * This method tries to create an IPAModule instance for every shared object - * found in \a libDir, and skips invalid IPA modules. + * Search a directory for .so files, allowing recursion down to sub-directories + * no further than the depth specified by \a maxDepth. * - * \return Number of modules loaded by this call + * Discovered shared objects are added to the \a files vector. */ -unsigned int IPAManager::addDir(const char *libDir) +void IPAManager::parseDir(const char *libDir, unsigned int maxDepth, + std::vector &files) { struct dirent *ent; DIR *dir; dir = opendir(libDir); if (!dir) - return 0; + return; - std::vector paths; while ((ent = readdir(dir)) != nullptr) { + if (ent->d_type == DT_DIR && maxDepth) { + if (strcmp(ent->d_name, ".") == 0 || + strcmp(ent->d_name, "..") == 0) + continue; + + std::string subdir = std::string(libDir) + "/" + ent->d_name; + + /* Recursion is limited to maxDepth. */ + parseDir(subdir.c_str(), maxDepth - 1, files); + + continue; + } + int offset = strlen(ent->d_name) - 3; if (offset < 0) continue; if (strcmp(&ent->d_name[offset], ".so")) continue; - paths.push_back(std::string(libDir) + "/" + ent->d_name); + files.push_back(std::string(libDir) + "/" + ent->d_name); } + closedir(dir); +} + +/** + * \brief Load IPA modules from a directory + * \param[in] libDir The directory to search for IPA modules + * \param[in] maxDepth The maximum depth of sub-directories to search + * + * This method tries to create an IPAModule instance for every shared object + * found in \a libDir, and skips invalid IPA modules. + * + * Sub-directories are searched up to a depth of \a maxDepth. A \a maxDepth + * value of 0 only searches the directory specified in \a libDir. + * + * \return Number of modules loaded by this call + */ +unsigned int IPAManager::addDir(const char *libDir, unsigned int maxDepth) +{ + std::vector files; + + parseDir(libDir, maxDepth, files); /* Ensure a stable ordering of modules. */ - std::sort(paths.begin(), paths.end()); + std::sort(files.begin(), files.end()); unsigned int count = 0; - for (const std::string &path : paths) { - IPAModule *ipaModule = new IPAModule(path); + for (const std::string &file : files) { + IPAModule *ipaModule = new IPAModule(file); if (!ipaModule->isValid()) { delete ipaModule; continue; } - LOG(IPAManager, Debug) << "Loaded IPA module '" << path << "'"; + LOG(IPAManager, Debug) << "Loaded IPA module '" << file << "'"; modules_.push_back(ipaModule); count++; -- cgit v1.2.1