#include "pch.h" #include "IEngine.h" #include "Crypto.h" #include #include using namespace craftlab::fakeraid; namespace craftlab::fakeraid { class Engine : public IEngine { public: Engine(const std::vector& path); void DirExistsOrThrow() const override; std::vector GetRootPaths() const override; std::vector GetPaths() const override; std::deque GetCurrentDir() const override; FileAndSumListByRepositoryIndex ListFiles() override; void Cd(const std::string& dirName) override; private: FileAndSumList ListFiles(const std::string& root, int repositoryIndex); std::string BuildCurrentDirPath(const std::string& root ="") const; const std::vector rootPaths; std::deque currentDir; }; } Engine::Engine(const std::vector& path): rootPaths(path), currentDir() {} std::vector Engine::GetRootPaths() const { return rootPaths; } std::vector Engine::GetPaths() const { std::vector paths; const std::string workingDir = BuildCurrentDirPath(); std::transform(rootPaths.begin(), rootPaths.end(), std::back_inserter(paths), [&workingDir](const std::string& val) { return val + "/" + workingDir; }); return paths; } std::deque Engine::GetCurrentDir() const { return currentDir; } std::string Engine::BuildCurrentDirPath(const std::string& root) const { std::stringstream ss; ss << root; bool written = !root.empty(); for (const std::string& path : currentDir) { if (written) ss << "/"; ss << path; written = true; } return ss.str(); } void Engine::Cd(const std::string& dirName) { currentDir.push_back(dirName); } FileAndSumList Engine::ListFiles(const std::string& root, int repositoryIndex) { FileAndSumList result; const std::string path = BuildCurrentDirPath(root); Crypto cryptoEngine; for (const std::filesystem::directory_entry& file : std::filesystem::directory_iterator(path)) { if (file.is_directory() || file.is_regular_file()) { FileAndSum fileInfos; fileInfos.fileName = file.path().filename().string(); fileInfos.isDir = file.is_directory(); fileInfos.repositoryIndex = repositoryIndex; try { cryptoEngine.Compute(path, fileInfos); } catch (std::runtime_error&) {} result.push_back(fileInfos); } } return result; } FileAndSumListByRepositoryIndex Engine::ListFiles() { FileAndSumListByRepositoryIndex result; int index = 0; for (const auto& i : rootPaths) { const FileAndSumList files = ListFiles(i, index++); result.FileAndSumListByRepositoryIndex.push_back(files); for (const FileAndSum& file : files) result.FileList[file.fileName] = file; } return result; } void Engine::DirExistsOrThrow() const { char errorBuffer[1024]; for (const std::string& fullPath : GetPaths()) { struct stat fileInfo; if (stat(fullPath.c_str(), &fileInfo)) { strerror_s(errorBuffer, errno); throw std::runtime_error("cannot access " + fullPath + ": " + errorBuffer); } if (!(fileInfo.st_mode & S_IFDIR)) { strerror_s(errorBuffer, ENOTDIR); throw std::runtime_error("cannot access " + fullPath + ": " + errorBuffer); } } } IEngine* EngineManager::Open(const std::vector& path) { return new Engine(path); }