Engine.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. private:
  23. FileAndSumList ListFiles(const std::string& root, int repositoryIndex);
  24. std::string BuildCurrentDirPath(const std::string& root ="") const;
  25. const std::vector<std::string> rootPaths;
  26. std::deque<std::string> currentDir;
  27. };
  28. }
  29. Engine::Engine(const std::vector<std::string>& path): rootPaths(path), currentDir()
  30. {}
  31. std::vector<std::string> Engine::GetRootPaths() const
  32. {
  33. return rootPaths;
  34. }
  35. std::vector<std::string> Engine::GetPaths() const
  36. {
  37. std::vector<std::string> paths;
  38. const std::string workingDir = BuildCurrentDirPath();
  39. std::transform(rootPaths.begin(), rootPaths.end(), std::back_inserter(paths), [&workingDir](const std::string& val) { return val + "/" + workingDir; });
  40. return paths;
  41. }
  42. std::deque<std::string> Engine::GetCurrentDir() const
  43. {
  44. return currentDir;
  45. }
  46. std::string Engine::BuildCurrentDirPath(const std::string& root) const
  47. {
  48. std::stringstream ss;
  49. ss << root;
  50. bool written = !root.empty();
  51. for (const std::string& path : currentDir)
  52. {
  53. if (written)
  54. ss << "/";
  55. ss << path;
  56. written = true;
  57. }
  58. return ss.str();
  59. }
  60. bool vectorEquals(const std::vector<std::string>& a, const std::deque<std::string>& b)
  61. {
  62. if (a.size() != b.size())
  63. return false;
  64. auto iterA = a.begin();
  65. auto iterB = b.begin();
  66. while (iterA != a.end())
  67. {
  68. if (*iterA != *iterB)
  69. return false;
  70. ++iterA;
  71. ++iterB;
  72. }
  73. return true;
  74. }
  75. bool Engine::SetWorkingDirectory(const std::vector<std::string>& path)
  76. {
  77. if (vectorEquals(path, currentDir))
  78. return false;
  79. currentDir.clear();
  80. std::copy(path.begin(), path.end(), std::back_inserter(currentDir));
  81. return true;
  82. }
  83. void Engine::Cd(const std::string& dirName)
  84. {
  85. currentDir.push_back(dirName);
  86. }
  87. FileAndSumList Engine::ListFiles(const std::string& root, int repositoryIndex)
  88. {
  89. FileAndSumList result;
  90. const std::string path = BuildCurrentDirPath(root);
  91. Crypto cryptoEngine;
  92. for (const std::filesystem::directory_entry& file : std::filesystem::directory_iterator(path))
  93. {
  94. if (file.is_directory() || file.is_regular_file())
  95. {
  96. FileAndSum fileInfos;
  97. fileInfos.fileName = file.path().filename().string();
  98. fileInfos.isDir = file.is_directory();
  99. fileInfos.repositoryIndex = repositoryIndex;
  100. try
  101. {
  102. cryptoEngine.Compute(path, fileInfos);
  103. }
  104. catch (std::runtime_error&)
  105. {}
  106. result.push_back(fileInfos);
  107. }
  108. }
  109. return result;
  110. }
  111. FileAndSumListByRepositoryIndex Engine::ListFiles()
  112. {
  113. FileAndSumListByRepositoryIndex result;
  114. int index = 0;
  115. for (const auto& i : rootPaths)
  116. {
  117. const FileAndSumList files = ListFiles(i, index++);
  118. result.FileAndSumListByRepositoryIndex.push_back(files);
  119. for (const FileAndSum& file : files)
  120. result.FileList[file.fileName] = file;
  121. }
  122. return result;
  123. }
  124. void Engine::DirExistsOrThrow() const
  125. {
  126. char errorBuffer[1024];
  127. for (const std::string& fullPath : GetPaths())
  128. {
  129. struct stat fileInfo;
  130. if (stat(fullPath.c_str(), &fileInfo))
  131. {
  132. strerror_s(errorBuffer, errno);
  133. throw std::runtime_error("cannot access " + fullPath + ": " + errorBuffer);
  134. }
  135. if (!(fileInfo.st_mode & S_IFDIR))
  136. {
  137. strerror_s(errorBuffer, ENOTDIR);
  138. throw std::runtime_error("cannot access " + fullPath + ": " + errorBuffer);
  139. }
  140. }
  141. }
  142. void Engine::RemoveFiles(const std::vector<std::string>& paths) const
  143. {
  144. for (const std::string& path: paths)
  145. std::filesystem::remove(path);
  146. }
  147. void Engine::RemoveDirs(const std::vector<std::string>& paths) const
  148. {
  149. for (const std::string& path : paths)
  150. std::filesystem::remove_all(path);
  151. }
  152. IEngine* EngineManager::Open(const std::vector<std::string>& path)
  153. {
  154. return new Engine(path);
  155. }