| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- #include "pch.h"
- #include "IEngine.h"
- #include "Crypto.h"
- #include <stdexcept>
- #include <filesystem>
- using namespace craftlab::fakeraid;
- namespace craftlab::fakeraid
- {
- class Engine : public IEngine
- {
- public:
- Engine(const std::vector<std::string>& path);
- void DirExistsOrThrow() const override;
- std::vector<std::string> GetRootPaths() const override;
- std::vector<std::string> GetPaths() const override;
- std::deque<std::string> GetCurrentDir() const override;
- bool SetWorkingDirectory(const std::vector<std::string>& path) override;
- FileAndSumListByRepositoryIndex ListFiles() override;
- void ListFilesRecur(FileAndSumListByRepositoryIndex*, bool* threadStopping) override;
- size_t CountFilesRecur() override;
- void Cd(const std::string& dirName) override;
- std::string BuildCurrentDirPath(const std::string& root, const PathParts& pathParts) const override;
- std::string BuildCurrentDirPath(const File& file) const override;
- std::string BuildFullPath(const File& file) const override;
- bool AnyFileExists(const std::vector<std::string>& files, const std::string& dropTo) const override;
- void RemoveFiles(const std::vector<std::string>& paths) const override;
- void RemoveDirs(const std::vector<std::string>& paths) const override;
- void CopyItems(const std::vector<CopyInstruction>& itemsToCopy) const override;
- void AddFiles(const std::vector<std::string>& files, const std::string& destination) const override;
- private:
- void ListFiles(FileAndSumListByRepositoryIndex& result, const PathParts& currentDir, std::string* lastFileScanned =nullptr, bool* threadStopping =nullptr);
- FileAndSumList ListFiles(const std::string& root, const PathParts& path, int repositoryIndex, std::string* lastFileScanned =nullptr, bool* threadStopping =nullptr);
- void CopyItem(const CopyInstruction& dst) const;
- const std::vector<std::string> rootPaths;
- std::deque<std::string> currentDir;
- };
- }
- Engine::Engine(const std::vector<std::string>& path): rootPaths(path), currentDir()
- {}
- std::vector<std::string> Engine::GetRootPaths() const
- {
- return rootPaths;
- }
- std::vector<std::string> Engine::GetPaths() const
- {
- std::vector<std::string> paths;
- const std::string workingDir = BuildCurrentDirPath("", currentDir);
- std::transform(rootPaths.begin(), rootPaths.end(), std::back_inserter(paths), [&workingDir](const std::string& val)
- {
- return (std::filesystem::path(val) / std::filesystem::path(workingDir)).string();
- });
- return paths;
- }
- std::deque<std::string> Engine::GetCurrentDir() const
- {
- return currentDir;
- }
- std::string Engine::BuildCurrentDirPath(const std::string& root, const PathParts& _currentDir) const
- {
- std::filesystem::path result(root);
- for (const std::string& path : _currentDir)
- result = result / path;
- return result.string();
- }
- std::string Engine::BuildCurrentDirPath(const File& file) const
- {
- std::filesystem::path result;
- for (const std::string& path : file.directory)
- result = result / path;
- result = result / file.fileName;
- return result.string();
- }
- std::string Engine::BuildFullPath(const File& file) const
- {
- std::filesystem::path result(rootPaths[file.repositoryIndex]);
- for (const std::string& path : file.directory)
- result /= path;
- result /= file.fileName;
- return result.string();
- }
- bool vectorEquals(const std::vector<std::string>& a, const std::deque<std::string>& b)
- {
- if (a.size() != b.size())
- return false;
- auto iterA = a.begin();
- auto iterB = b.begin();
- while (iterA != a.end())
- {
- if (*iterA != *iterB)
- return false;
- ++iterA;
- ++iterB;
- }
- return true;
- }
- bool Engine::SetWorkingDirectory(const std::vector<std::string>& path)
- {
- if (vectorEquals(path, currentDir))
- return false;
- currentDir.clear();
- std::copy(path.begin(), path.end(), std::back_inserter(currentDir));
- return true;
- }
- void Engine::Cd(const std::string& dirName)
- {
- currentDir.push_back(dirName);
- }
- FileAndSumList Engine::ListFiles(const std::string& root, const std::deque<std::string>& wd, int repositoryIndex, std::string* lastFileScanned, bool* threadStopping)
- {
- FileAndSumList result {};
- const std::string path = BuildCurrentDirPath(root, wd);
- Crypto cryptoEngine;
- std::filesystem::directory_iterator directoryIterator; // FIXME error handling
- try
- {
- directoryIterator = std::filesystem::directory_iterator(path);
- }
- catch (std::exception& e)
- {
- return result; // FIXME
- }
- for (const std::filesystem::directory_entry& file : directoryIterator)
- {
- bool isDirectory = false;
- bool isFile = false;
- try
- {
- isDirectory = file.is_directory();
- isFile = file.is_regular_file();
- }
- catch (std::exception& e)
- {}
- if (isDirectory || isFile)
- {
- FileAndSum fileInfos;
- fileInfos.fileName = file.path().filename().string();
- fileInfos.isDir = file.is_directory();
- fileInfos.directory = wd;
- fileInfos.repositoryIndex = repositoryIndex;
- if (nullptr != lastFileScanned)
- *lastFileScanned = BuildCurrentDirPath(fileInfos);
- try
- {
- cryptoEngine.Compute(path, fileInfos);
- }
- catch (std::runtime_error&)
- {
- }
- result.push_back(fileInfos);
- }
- if (threadStopping && *threadStopping)
- return result;
- }
- return result;
- }
- void Engine::ListFiles(FileAndSumListByRepositoryIndex& result, const std::deque<std::string>& currentDir, std::string* lastFileScanned, bool* threadStopping)
- {
- int index = 0;
- for (const auto& i : rootPaths)
- {
- const FileAndSumList files = ListFiles(i, currentDir, index++, lastFileScanned, threadStopping);
- result.FileAndSumListByRepositoryIndex.push_back(files);
- for (const FileAndSum& file : files)
- result.FileList[BuildCurrentDirPath(file)] = file;
- if (threadStopping && *threadStopping)
- return;
- }
- }
- FileAndSumListByRepositoryIndex Engine::ListFiles()
- {
- FileAndSumListByRepositoryIndex result;
- ListFiles(result, currentDir);
- return result;
- }
- void Engine::ListFilesRecur(FileAndSumListByRepositoryIndex* result, bool* threadStopping)
- {
- std::deque<PathParts> itemsToDo { currentDir };
- do
- {
- FileAndSumListByRepositoryIndex newItems;
- const PathParts currentPath = itemsToDo.front();
- ListFiles(newItems, currentPath, &result->lastInsertedFilename, threadStopping);
- itemsToDo.pop_front();
- std::copy(newItems.FileAndSumListByRepositoryIndex.begin(), newItems.FileAndSumListByRepositoryIndex.end(), std::back_inserter(result->FileAndSumListByRepositoryIndex));
- for (const auto& file : newItems.FileList)
- {
- result->FileList[file.first] = file.second;
- if (file.second.isDir)
- {
- PathParts dirPath = currentPath;
- dirPath.push_back(file.second.fileName);
- itemsToDo.push_back(dirPath);
- }
- }
- } while (!itemsToDo.empty() && !*threadStopping);
- }
- size_t Engine::CountFilesRecur()
- {
- size_t result =0;
- std::deque<std::filesystem::path> itemsToDo;
- for (const auto& i: rootPaths)
- itemsToDo.push_back(i);
- do
- {
- std::filesystem::directory_iterator directoryIterator; // FIXME error handling
- try
- {
- directoryIterator = std::filesystem::directory_iterator(itemsToDo.front());
- }
- catch (std::exception& e)
- {
- itemsToDo.pop_front();
- continue;
- }
- for (const std::filesystem::directory_entry& file : directoryIterator)
- {
- try {
- if (file.is_regular_file())
- ++result;
- else if (file.is_directory())
- {
- itemsToDo.push_back(file.path());
- ++result;
- }
- }
- catch (std::exception)
- {}
- }
- itemsToDo.pop_front();
- } while (!itemsToDo.empty());
- 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);
- }
- }
- }
- void Engine::RemoveFiles(const std::vector<std::string>& paths) const
- {
- for (const std::string& path: paths)
- std::filesystem::remove(path); // FIXME error handling
- }
- void Engine::RemoveDirs(const std::vector<std::string>& paths) const
- {
- for (const std::string& path : paths)
- std::filesystem::remove_all(path); // FIXME error handling
- }
- void Engine::CopyItem(const IEngine::CopyInstruction& item) const
- {
- std::filesystem::copy(item.source, item.destination, std::filesystem::copy_options::overwrite_existing | std::filesystem::copy_options::recursive); // FIXME error handling
- }
- void Engine::CopyItems(const std::vector<IEngine::CopyInstruction>& paths) const
- {
- for (const CopyInstruction& item: paths)
- CopyItem(item);
- }
- bool Engine::AnyFileExists(const std::vector<std::string>& files, const std::string& destination) const
- {
- for (const std::string _file : files)
- {
- std::filesystem::path file(_file);
- for (const std::string& root : rootPaths)
- {
- std::filesystem::path outputPath(root + "/" + destination);
- outputPath /= file.filename();
- if (std::filesystem::exists(outputPath))
- {
- if (std::filesystem::equivalent(outputPath, file)) // FIXME error handling
- throw IEngine::SameFileError();
- return true;
- }
- }
- }
- return false;
- }
- void Engine::AddFiles(const std::vector<std::string>& files, const std::string& _destination) const
- {
- for (const std::string _file : files)
- {
- std::filesystem::path file(_file);
- for (const std::string& root : rootPaths)
- {
- std::filesystem::path destination(root + "/" + _destination);
- destination /= file.filename();
- std::filesystem::copy(file, destination, std::filesystem::copy_options::overwrite_existing | std::filesystem::copy_options::recursive); // FIXME error handling
- }
- }
- }
- IEngine* EngineManager::Open(const std::vector<std::string>& path)
- {
- return new Engine(path);
- }
|