1
0

Engine.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include "pch.h"
  2. #include "IEngine.h"
  3. #include "Crypto.h"
  4. #include <stdexcept>
  5. #include <filesystem>
  6. using namespace craftlab::fakeraid;
  7. namespace craftlab::fakeraid
  8. {
  9. class Engine : public IEngine
  10. {
  11. public:
  12. Engine(const std::vector<std::string>& path);
  13. void DirExistsOrThrow() const override;
  14. std::vector<std::string> GetRootPaths() const override;
  15. std::vector<std::string> GetPaths() const override;
  16. std::deque<std::string> GetCurrentDir() const override;
  17. bool SetWorkingDirectory(const std::vector<std::string>& path) override;
  18. FileAndSumListByRepositoryIndex ListFiles() override;
  19. void Cd(const std::string& dirName) override;
  20. void RemoveFiles(const std::vector<std::string>& paths) const override;
  21. void RemoveDirs(const std::vector<std::string>& paths) const override;
  22. void CopyItems(const std::vector<CopyInstruction>& itemsToCopy) const override;
  23. private:
  24. FileAndSumList ListFiles(const std::string& root, int repositoryIndex);
  25. std::string BuildCurrentDirPath(const std::string& root ="") const;
  26. void CopyItem(const CopyInstruction& dst) const;
  27. const std::vector<std::string> rootPaths;
  28. std::deque<std::string> currentDir;
  29. };
  30. }
  31. Engine::Engine(const std::vector<std::string>& path): rootPaths(path), currentDir()
  32. {}
  33. std::vector<std::string> Engine::GetRootPaths() const
  34. {
  35. return rootPaths;
  36. }
  37. std::vector<std::string> Engine::GetPaths() const
  38. {
  39. std::vector<std::string> paths;
  40. const std::string workingDir = BuildCurrentDirPath();
  41. std::transform(rootPaths.begin(), rootPaths.end(), std::back_inserter(paths), [&workingDir](const std::string& val)
  42. {
  43. return (std::filesystem::path(val) / std::filesystem::path(workingDir)).string();
  44. });
  45. return paths;
  46. }
  47. std::deque<std::string> Engine::GetCurrentDir() const
  48. {
  49. return currentDir;
  50. }
  51. std::string Engine::BuildCurrentDirPath(const std::string& root) const
  52. {
  53. std::stringstream ss;
  54. ss << root;
  55. bool written = !root.empty();
  56. for (const std::string& path : currentDir)
  57. {
  58. if (written)
  59. ss << "/";
  60. ss << path;
  61. written = true;
  62. }
  63. return ss.str();
  64. }
  65. bool vectorEquals(const std::vector<std::string>& a, const std::deque<std::string>& b)
  66. {
  67. if (a.size() != b.size())
  68. return false;
  69. auto iterA = a.begin();
  70. auto iterB = b.begin();
  71. while (iterA != a.end())
  72. {
  73. if (*iterA != *iterB)
  74. return false;
  75. ++iterA;
  76. ++iterB;
  77. }
  78. return true;
  79. }
  80. bool Engine::SetWorkingDirectory(const std::vector<std::string>& path)
  81. {
  82. if (vectorEquals(path, currentDir))
  83. return false;
  84. currentDir.clear();
  85. std::copy(path.begin(), path.end(), std::back_inserter(currentDir));
  86. return true;
  87. }
  88. void Engine::Cd(const std::string& dirName)
  89. {
  90. currentDir.push_back(dirName);
  91. }
  92. FileAndSumList Engine::ListFiles(const std::string& root, int repositoryIndex)
  93. {
  94. FileAndSumList result;
  95. const std::string path = BuildCurrentDirPath(root);
  96. Crypto cryptoEngine;
  97. for (const std::filesystem::directory_entry& file : std::filesystem::directory_iterator(path))
  98. {
  99. if (file.is_directory() || file.is_regular_file())
  100. {
  101. FileAndSum fileInfos;
  102. fileInfos.fileName = file.path().filename().string();
  103. fileInfos.isDir = file.is_directory();
  104. fileInfos.repositoryIndex = repositoryIndex;
  105. try
  106. {
  107. cryptoEngine.Compute(path, fileInfos);
  108. }
  109. catch (std::runtime_error&)
  110. {}
  111. result.push_back(fileInfos);
  112. }
  113. }
  114. return result;
  115. }
  116. FileAndSumListByRepositoryIndex Engine::ListFiles()
  117. {
  118. FileAndSumListByRepositoryIndex result;
  119. int index = 0;
  120. for (const auto& i : rootPaths)
  121. {
  122. const FileAndSumList files = ListFiles(i, index++);
  123. result.FileAndSumListByRepositoryIndex.push_back(files);
  124. for (const FileAndSum& file : files)
  125. result.FileList[file.fileName] = file;
  126. }
  127. return result;
  128. }
  129. void Engine::DirExistsOrThrow() const
  130. {
  131. char errorBuffer[1024];
  132. for (const std::string& fullPath : GetPaths())
  133. {
  134. struct stat fileInfo;
  135. if (stat(fullPath.c_str(), &fileInfo))
  136. {
  137. strerror_s(errorBuffer, errno);
  138. throw std::runtime_error("cannot access " + fullPath + ": " + errorBuffer);
  139. }
  140. if (!(fileInfo.st_mode & S_IFDIR))
  141. {
  142. strerror_s(errorBuffer, ENOTDIR);
  143. throw std::runtime_error("cannot access " + fullPath + ": " + errorBuffer);
  144. }
  145. }
  146. }
  147. void Engine::RemoveFiles(const std::vector<std::string>& paths) const
  148. {
  149. for (const std::string& path: paths)
  150. std::filesystem::remove(path);
  151. }
  152. void Engine::RemoveDirs(const std::vector<std::string>& paths) const
  153. {
  154. for (const std::string& path : paths)
  155. std::filesystem::remove_all(path);
  156. }
  157. void Engine::CopyItem(const IEngine::CopyInstruction& item) const
  158. {
  159. std::filesystem::copy(item.source, item.destination, std::filesystem::copy_options::overwrite_existing | std::filesystem::copy_options::recursive);
  160. }
  161. void Engine::CopyItems(const std::vector<IEngine::CopyInstruction>& paths) const
  162. {
  163. for (const CopyInstruction& item: paths)
  164. CopyItem(item);
  165. }
  166. IEngine* EngineManager::Open(const std::vector<std::string>& path)
  167. {
  168. return new Engine(path);
  169. }