vfs_real.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/common_paths.h"
  5. #include "common/logging/log.h"
  6. #include "core/file_sys/vfs_real.h"
  7. namespace FileSys {
  8. static std::string PermissionsToCharArray(Mode perms) {
  9. std::string out;
  10. switch (perms) {
  11. case Mode::Read:
  12. out += "r";
  13. break;
  14. case Mode::Write:
  15. out += "r+";
  16. break;
  17. case Mode::Append:
  18. out += "a";
  19. break;
  20. }
  21. return out + "b";
  22. }
  23. RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_)
  24. : backing(path_, PermissionsToCharArray(perms_).c_str()), path(path_),
  25. parent_path(FileUtil::GetParentPath(path_)),
  26. path_components(FileUtil::SplitPathComponents(path_)),
  27. parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
  28. perms(perms_) {}
  29. std::string RealVfsFile::GetName() const {
  30. return path_components.back();
  31. }
  32. size_t RealVfsFile::GetSize() const {
  33. return backing.GetSize();
  34. }
  35. bool RealVfsFile::Resize(size_t new_size) {
  36. return backing.Resize(new_size);
  37. }
  38. std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
  39. return std::make_shared<RealVfsDirectory>(parent_path, perms);
  40. }
  41. bool RealVfsFile::IsWritable() const {
  42. return perms == Mode::Append || perms == Mode::Write;
  43. }
  44. bool RealVfsFile::IsReadable() const {
  45. return perms == Mode::Read || perms == Mode::Write;
  46. }
  47. size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const {
  48. if (!backing.Seek(offset, SEEK_SET))
  49. return 0;
  50. return backing.ReadBytes(data, length);
  51. }
  52. size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) {
  53. if (!backing.Seek(offset, SEEK_SET))
  54. return 0;
  55. return backing.WriteBytes(data, length);
  56. }
  57. bool RealVfsFile::Rename(const std::string& name) {
  58. const auto out = FileUtil::Rename(GetName(), name);
  59. path = parent_path + DIR_SEP + name;
  60. path_components = parent_components;
  61. path_components.push_back(name);
  62. backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str());
  63. return out;
  64. }
  65. bool RealVfsFile::Close() {
  66. return backing.Close();
  67. }
  68. RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_)
  69. : path(FileUtil::RemoveTrailingSlash(path_)), parent_path(FileUtil::GetParentPath(path)),
  70. path_components(FileUtil::SplitPathComponents(path)),
  71. parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
  72. perms(perms_) {
  73. if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append))
  74. FileUtil::CreateDir(path);
  75. unsigned size;
  76. if (perms == Mode::Append)
  77. return;
  78. FileUtil::ForeachDirectoryEntry(
  79. &size, path,
  80. [this](unsigned* entries_out, const std::string& directory, const std::string& filename) {
  81. std::string full_path = directory + DIR_SEP + filename;
  82. if (FileUtil::IsDirectory(full_path))
  83. subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(full_path, perms));
  84. else
  85. files.emplace_back(std::make_shared<RealVfsFile>(full_path, perms));
  86. return true;
  87. });
  88. }
  89. std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const {
  90. return std::vector<std::shared_ptr<VfsFile>>(files);
  91. }
  92. std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const {
  93. return std::vector<std::shared_ptr<VfsDirectory>>(subdirectories);
  94. }
  95. bool RealVfsDirectory::IsWritable() const {
  96. return perms == Mode::Write || perms == Mode::Append;
  97. }
  98. bool RealVfsDirectory::IsReadable() const {
  99. return perms == Mode::Read || perms == Mode::Write;
  100. }
  101. std::string RealVfsDirectory::GetName() const {
  102. return path_components.back();
  103. }
  104. std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const {
  105. if (path_components.size() <= 1)
  106. return nullptr;
  107. return std::make_shared<RealVfsDirectory>(parent_path, perms);
  108. }
  109. std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(const std::string& name) {
  110. if (!FileUtil::CreateDir(path + DIR_SEP + name))
  111. return nullptr;
  112. subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(path + DIR_SEP + name, perms));
  113. return subdirectories.back();
  114. }
  115. std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(const std::string& name) {
  116. if (!FileUtil::CreateEmptyFile(path + DIR_SEP + name))
  117. return nullptr;
  118. files.emplace_back(std::make_shared<RealVfsFile>(path + DIR_SEP + name, perms));
  119. return files.back();
  120. }
  121. bool RealVfsDirectory::DeleteSubdirectory(const std::string& name) {
  122. return FileUtil::DeleteDirRecursively(path + DIR_SEP + name);
  123. }
  124. bool RealVfsDirectory::DeleteFile(const std::string& name) {
  125. auto file = GetFile(name);
  126. if (file == nullptr)
  127. return false;
  128. files.erase(std::find(files.begin(), files.end(), file));
  129. auto real_file = std::static_pointer_cast<RealVfsFile>(file);
  130. real_file->Close();
  131. return FileUtil::Delete(path + DIR_SEP + name);
  132. }
  133. bool RealVfsDirectory::Rename(const std::string& name) {
  134. return FileUtil::Rename(path, parent_path + DIR_SEP + name);
  135. }
  136. bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
  137. auto iter = std::find(files.begin(), files.end(), file);
  138. if (iter == files.end())
  139. return false;
  140. files[iter - files.begin()] = files.back();
  141. files.pop_back();
  142. subdirectories.emplace_back(dir);
  143. return true;
  144. }
  145. } // namespace FileSys