summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-08-03 11:50:00 -0400
committerGravatar Zach Hilman2018-08-08 21:18:45 -0400
commit2de2ec25d6e8971809f98ebe36996c00e0f89f2d (patch)
tree7b8ec6b50b8c5de91eef426c3ad3cb4d0d7c2e05 /src
parentfile_util: Add platform-specific slash option to SanitizePath (diff)
downloadyuzu-2de2ec25d6e8971809f98ebe36996c00e0f89f2d.tar.gz
yuzu-2de2ec25d6e8971809f98ebe36996c00e0f89f2d.tar.xz
yuzu-2de2ec25d6e8971809f98ebe36996c00e0f89f2d.zip
vfs: Add RealVfsFilesystem implementation
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/vfs_real.cpp327
-rw-r--r--src/core/file_sys/vfs_real.h44
2 files changed, 290 insertions, 81 deletions
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 82d54da4a..2923a8e6a 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -36,8 +36,164 @@ static std::string ModeFlagsToString(Mode mode) {
36 return mode_str; 36 return mode_str;
37} 37}
38 38
39RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_) 39RealVfsFilesystem::RealVfsFilesystem() : VfsFilesystem(nullptr) {}
40 : backing(path_, ModeFlagsToString(perms_).c_str()), path(path_), 40
41std::string RealVfsFilesystem::GetName() const {
42 return "Real";
43}
44
45bool RealVfsFilesystem::IsReadable() const {
46 return true;
47}
48
49bool RealVfsFilesystem::IsWritable() const {
50 return true;
51}
52
53VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
54 const auto path = FileUtil::SanitizePath(path_, true);
55 if (!FileUtil::Exists(path))
56 return VfsEntryType::None;
57 if (FileUtil::IsDirectory(path))
58 return VfsEntryType::Directory;
59
60 return VfsEntryType::File;
61}
62
63VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
64 const auto path = FileUtil::SanitizePath(path_, true);
65 if (cache.find(path) != cache.end()) {
66 auto weak = cache[path];
67 if (!weak.expired()) {
68 return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms));
69 }
70 }
71
72 if (!FileUtil::Exists(path) && (perms & Mode::WriteAppend) != 0)
73 FileUtil::CreateEmptyFile(path);
74
75 auto backing = std::make_shared<FileUtil::IOFile>(path, ModeFlagsToString(perms).c_str());
76 cache[path] = backing;
77
78 // Cannot use make_shared as RealVfsFile constructor is private
79 return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms));
80}
81
82VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
83 const auto path = FileUtil::SanitizePath(path_, true);
84 if (!FileUtil::Exists(path) && !FileUtil::CreateEmptyFile(path))
85 return nullptr;
86 return OpenFile(path, perms);
87}
88
89VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) {
90 const auto old_path = FileUtil::SanitizePath(old_path_, true);
91 const auto new_path = FileUtil::SanitizePath(new_path_, true);
92
93 if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
94 FileUtil::IsDirectory(old_path) || !FileUtil::Copy(old_path, new_path))
95 return nullptr;
96 return OpenFile(new_path, Mode::ReadWrite);
97}
98
99VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {
100 const auto old_path = FileUtil::SanitizePath(old_path_, true);
101 const auto new_path = FileUtil::SanitizePath(new_path_, true);
102
103 if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
104 FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path))
105 return nullptr;
106
107 if (cache.find(old_path) != cache.end()) {
108 auto cached = cache[old_path];
109 if (!cached.expired()) {
110 auto file = cached.lock();
111 file->Open(new_path, "r+b");
112 cache.erase(old_path);
113 cache[new_path] = file;
114 }
115 }
116 return OpenFile(new_path, Mode::ReadWrite);
117}
118
119bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
120 const auto path = FileUtil::SanitizePath(path_, true);
121 if (cache.find(path) != cache.end()) {
122 if (!cache[path].expired())
123 cache[path].lock()->Close();
124 cache.erase(path);
125 }
126 return FileUtil::Delete(path);
127}
128
129VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) {
130 const auto path = FileUtil::SanitizePath(path_, true);
131 // Cannot use make_shared as RealVfsDirectory constructor is private
132 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
133}
134
135VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) {
136 const auto path = FileUtil::SanitizePath(path_, true);
137 if (!FileUtil::Exists(path) && !FileUtil::CreateDir(path))
138 return nullptr;
139 // Cannot use make_shared as RealVfsDirectory constructor is private
140 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
141}
142
143VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_,
144 std::string_view new_path_) {
145 const auto old_path = FileUtil::SanitizePath(old_path_, true);
146 const auto new_path = FileUtil::SanitizePath(new_path_, true);
147 if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
148 !FileUtil::IsDirectory(old_path))
149 return nullptr;
150 FileUtil::CopyDir(old_path, new_path);
151 return OpenDirectory(new_path, Mode::ReadWrite);
152}
153
154VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
155 std::string_view new_path_) {
156 const auto old_path = FileUtil::SanitizePath(old_path_, true);
157 const auto new_path = FileUtil::SanitizePath(new_path_, true);
158 if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
159 FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path))
160 return nullptr;
161
162 for (auto& kv : cache) {
163 // Path in cache starts with old_path
164 if (kv.first.rfind(old_path, 0) == 0) {
165 const auto file_old_path = FileUtil::SanitizePath(kv.first, true);
166 const auto file_new_path =
167 FileUtil::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()), true);
168 auto cached = cache[file_old_path];
169 if (!cached.expired()) {
170 auto file = cached.lock();
171 file->Open(file_new_path, "r+b");
172 cache.erase(file_old_path);
173 cache[file_new_path] = file;
174 }
175 }
176 }
177
178 return OpenDirectory(new_path, Mode::ReadWrite);
179}
180
181bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {
182 const auto path = FileUtil::SanitizePath(path_, true);
183 for (auto& kv : cache) {
184 // Path in cache starts with old_path
185 if (kv.first.rfind(path, 0) == 0) {
186 if (!cache[kv.first].expired())
187 cache[kv.first].lock()->Close();
188 cache.erase(kv.first);
189 }
190 }
191 return FileUtil::DeleteDirRecursively(path);
192}
193
194RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FileUtil::IOFile> backing_,
195 const std::string& path_, Mode perms_)
196 : base(base_), backing(std::move(backing_)), path(path_),
41 parent_path(FileUtil::GetParentPath(path_)), 197 parent_path(FileUtil::GetParentPath(path_)),
42 path_components(FileUtil::SplitPathComponents(path_)), 198 path_components(FileUtil::SplitPathComponents(path_)),
43 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), 199 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
@@ -48,15 +204,15 @@ std::string RealVfsFile::GetName() const {
48} 204}
49 205
50size_t RealVfsFile::GetSize() const { 206size_t RealVfsFile::GetSize() const {
51 return backing.GetSize(); 207 return backing->GetSize();
52} 208}
53 209
54bool RealVfsFile::Resize(size_t new_size) { 210bool RealVfsFile::Resize(size_t new_size) {
55 return backing.Resize(new_size); 211 return backing->Resize(new_size);
56} 212}
57 213
58std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const { 214std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
59 return std::make_shared<RealVfsDirectory>(parent_path, perms); 215 return base.OpenDirectory(parent_path, perms);
60} 216}
61 217
62bool RealVfsFile::IsWritable() const { 218bool RealVfsFile::IsWritable() const {
@@ -68,62 +224,118 @@ bool RealVfsFile::IsReadable() const {
68} 224}
69 225
70size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const { 226size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const {
71 if (!backing.Seek(offset, SEEK_SET)) 227 if (!backing->Seek(offset, SEEK_SET))
72 return 0; 228 return 0;
73 return backing.ReadBytes(data, length); 229 return backing->ReadBytes(data, length);
74} 230}
75 231
76size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) { 232size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) {
77 if (!backing.Seek(offset, SEEK_SET)) 233 if (!backing->Seek(offset, SEEK_SET))
78 return 0; 234 return 0;
79 return backing.WriteBytes(data, length); 235 return backing->WriteBytes(data, length);
80} 236}
81 237
82bool RealVfsFile::Rename(std::string_view name) { 238bool RealVfsFile::Rename(std::string_view name) {
83 std::string name_str(name.begin(), name.end()); 239 return base.MoveFile(path, parent_path + DIR_SEP + std::string(name)) != nullptr;
84 const auto out = FileUtil::Rename(GetName(), name_str); 240}
85 241
86 path = (parent_path + DIR_SEP).append(name); 242bool RealVfsFile::Close() {
87 path_components = parent_components; 243 return backing->Close();
88 path_components.push_back(std::move(name_str)); 244}
89 backing = FileUtil::IOFile(path, ModeFlagsToString(perms).c_str()); 245
246// TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if
247// constexpr' because there is a compile error in the branch not used.
248
249template <>
250std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>() const {
251 if (perms == Mode::Append)
252 return {};
253
254 std::vector<VirtualFile> out;
255 FileUtil::ForeachDirectoryEntry(
256 nullptr, path,
257 [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) {
258 const std::string full_path = directory + DIR_SEP + filename;
259 if (!FileUtil::IsDirectory(full_path))
260 out.emplace_back(base.OpenFile(full_path, perms));
261 return true;
262 });
90 263
91 return out; 264 return out;
92} 265}
93 266
94bool RealVfsFile::Close() { 267template <>
95 return backing.Close(); 268std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDirectory>() const {
269 if (perms == Mode::Append)
270 return {};
271
272 std::vector<VirtualDir> out;
273 FileUtil::ForeachDirectoryEntry(
274 nullptr, path,
275 [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) {
276 const std::string full_path = directory + DIR_SEP + filename;
277 if (FileUtil::IsDirectory(full_path))
278 out.emplace_back(base.OpenDirectory(full_path, perms));
279 return true;
280 });
281
282 return out;
96} 283}
97 284
98RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_) 285RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_)
99 : path(FileUtil::RemoveTrailingSlash(path_)), parent_path(FileUtil::GetParentPath(path)), 286 : base(base_), path(FileUtil::RemoveTrailingSlash(path_)),
287 parent_path(FileUtil::GetParentPath(path)),
100 path_components(FileUtil::SplitPathComponents(path)), 288 path_components(FileUtil::SplitPathComponents(path)),
101 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), 289 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
102 perms(perms_) { 290 perms(perms_) {
103 if (!FileUtil::Exists(path) && perms & Mode::WriteAppend) 291 if (!FileUtil::Exists(path) && perms & Mode::WriteAppend)
104 FileUtil::CreateDir(path); 292 FileUtil::CreateDir(path);
293}
105 294
106 if (perms == Mode::Append) 295std::shared_ptr<VfsFile> RealVfsDirectory::GetFileRelative(std::string_view path) const {
107 return; 296 const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
297 if (!FileUtil::Exists(full_path))
298 return nullptr;
299 return base.OpenFile(full_path, perms);
300}
108 301
109 FileUtil::ForeachDirectoryEntry( 302std::shared_ptr<VfsDirectory> RealVfsDirectory::GetDirectoryRelative(std::string_view path) const {
110 nullptr, path, 303 const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
111 [this](u64* entries_out, const std::string& directory, const std::string& filename) { 304 if (!FileUtil::Exists(full_path))
112 std::string full_path = directory + DIR_SEP + filename; 305 return nullptr;
113 if (FileUtil::IsDirectory(full_path)) 306 return base.OpenDirectory(full_path, perms);
114 subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(full_path, perms)); 307}
115 else 308
116 files.emplace_back(std::make_shared<RealVfsFile>(full_path, perms)); 309std::shared_ptr<VfsFile> RealVfsDirectory::GetFile(std::string_view name) const {
117 return true; 310 return GetFileRelative(name);
118 }); 311}
312
313std::shared_ptr<VfsDirectory> RealVfsDirectory::GetSubdirectory(std::string_view name) const {
314 return GetDirectoryRelative(name);
315}
316
317std::shared_ptr<VfsFile> RealVfsDirectory::CreateFileRelative(std::string_view path) {
318 const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
319 return base.CreateFile(full_path, perms);
320}
321
322std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateDirectoryRelative(std::string_view path) {
323 const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
324 auto parent = std::string(FileUtil::GetParentPath(full_path));
325 return base.CreateDirectory(full_path, perms);
326}
327
328bool RealVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) {
329 auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(name));
330 return base.DeleteDirectory(full_path);
119} 331}
120 332
121std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const { 333std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const {
122 return files; 334 return IterateEntries<RealVfsFile, VfsFile>();
123} 335}
124 336
125std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const { 337std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const {
126 return subdirectories; 338 return IterateEntries<RealVfsDirectory, VfsDirectory>();
127} 339}
128 340
129bool RealVfsDirectory::IsWritable() const { 341bool RealVfsDirectory::IsWritable() const {
@@ -142,57 +354,32 @@ std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const {
142 if (path_components.size() <= 1) 354 if (path_components.size() <= 1)
143 return nullptr; 355 return nullptr;
144 356
145 return std::make_shared<RealVfsDirectory>(parent_path, perms); 357 return base.OpenDirectory(parent_path, perms);
146} 358}
147 359
148std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(std::string_view name) { 360std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(std::string_view name) {
149 const std::string subdir_path = (path + DIR_SEP).append(name); 361 const std::string subdir_path = (path + DIR_SEP).append(name);
150 362 return base.CreateDirectory(subdir_path, perms);
151 if (!FileUtil::CreateDir(subdir_path)) {
152 return nullptr;
153 }
154
155 subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(subdir_path, perms));
156 return subdirectories.back();
157} 363}
158 364
159std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(std::string_view name) { 365std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(std::string_view name) {
160 const std::string file_path = (path + DIR_SEP).append(name); 366 const std::string file_path = (path + DIR_SEP).append(name);
161 367 return base.CreateFile(file_path, perms);
162 if (!FileUtil::CreateEmptyFile(file_path)) {
163 return nullptr;
164 }
165
166 files.emplace_back(std::make_shared<RealVfsFile>(file_path, perms));
167 return files.back();
168} 368}
169 369
170bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) { 370bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) {
171 const std::string subdir_path = (path + DIR_SEP).append(name); 371 const std::string subdir_path = (path + DIR_SEP).append(name);
172 372 return base.DeleteDirectory(subdir_path);
173 return FileUtil::DeleteDirRecursively(subdir_path);
174} 373}
175 374
176bool RealVfsDirectory::DeleteFile(std::string_view name) { 375bool RealVfsDirectory::DeleteFile(std::string_view name) {
177 const auto file = GetFile(name);
178
179 if (file == nullptr) {
180 return false;
181 }
182
183 files.erase(std::find(files.begin(), files.end(), file));
184
185 auto real_file = std::static_pointer_cast<RealVfsFile>(file);
186 real_file->Close();
187
188 const std::string file_path = (path + DIR_SEP).append(name); 376 const std::string file_path = (path + DIR_SEP).append(name);
189 return FileUtil::Delete(file_path); 377 return base.DeleteFile(file_path);
190} 378}
191 379
192bool RealVfsDirectory::Rename(std::string_view name) { 380bool RealVfsDirectory::Rename(std::string_view name) {
193 const std::string new_name = (parent_path + DIR_SEP).append(name); 381 const std::string new_name = (parent_path + DIR_SEP).append(name);
194 382 return base.MoveFile(path, new_name) != nullptr;
195 return FileUtil::Rename(path, new_name);
196} 383}
197 384
198std::string RealVfsDirectory::GetFullPath() const { 385std::string RealVfsDirectory::GetFullPath() const {
@@ -202,16 +389,6 @@ std::string RealVfsDirectory::GetFullPath() const {
202} 389}
203 390
204bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { 391bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
205 const auto iter = std::find(files.begin(), files.end(), file); 392 return false;
206 if (iter == files.end())
207 return false;
208
209 const std::ptrdiff_t offset = std::distance(files.begin(), iter);
210 files[offset] = files.back();
211 files.pop_back();
212
213 subdirectories.emplace_back(std::move(dir));
214
215 return true;
216} 393}
217} // namespace FileSys 394} // namespace FileSys
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index 243d58576..dbb381a2a 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -6,18 +6,45 @@
6 6
7#include <string_view> 7#include <string_view>
8 8
9#include <boost/container/flat_map.hpp>
9#include "common/file_util.h" 10#include "common/file_util.h"
10#include "core/file_sys/mode.h" 11#include "core/file_sys/mode.h"
11#include "core/file_sys/vfs.h" 12#include "core/file_sys/vfs.h"
12 13
13namespace FileSys { 14namespace FileSys {
14 15
16class RealVfsFilesystem : public VfsFilesystem {
17public:
18 RealVfsFilesystem();
19
20 std::string GetName() const override;
21 bool IsReadable() const override;
22 bool IsWritable() const override;
23 VfsEntryType GetEntryType(std::string_view path) const override;
24 VirtualFile OpenFile(std::string_view path, Mode perms = Mode::Read) override;
25 VirtualFile CreateFile(std::string_view path, Mode perms = Mode::ReadWrite) override;
26 VirtualFile CopyFile(std::string_view old_path, std::string_view new_path) override;
27 VirtualFile MoveFile(std::string_view old_path, std::string_view new_path) override;
28 bool DeleteFile(std::string_view path) override;
29 VirtualDir OpenDirectory(std::string_view path, Mode perms = Mode::Read) override;
30 VirtualDir CreateDirectory(std::string_view path, Mode perms = Mode::ReadWrite) override;
31 VirtualDir CopyDirectory(std::string_view old_path, std::string_view new_path) override;
32 VirtualDir MoveDirectory(std::string_view old_path, std::string_view new_path) override;
33 bool DeleteDirectory(std::string_view path) override;
34
35private:
36 boost::container::flat_map<std::string, std::weak_ptr<FileUtil::IOFile>> cache;
37};
38
15// An implmentation of VfsFile that represents a file on the user's computer. 39// An implmentation of VfsFile that represents a file on the user's computer.
16struct RealVfsFile : public VfsFile { 40class RealVfsFile : public VfsFile {
17 friend struct RealVfsDirectory; 41 friend class RealVfsDirectory;
42 friend class RealVfsFilesystem;
18 43
19 RealVfsFile(const std::string& name, Mode perms = Mode::Read); 44 RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<FileUtil::IOFile> backing,
45 const std::string& path, Mode perms = Mode::Read);
20 46
47public:
21 std::string GetName() const override; 48 std::string GetName() const override;
22 size_t GetSize() const override; 49 size_t GetSize() const override;
23 bool Resize(size_t new_size) override; 50 bool Resize(size_t new_size) override;
@@ -31,7 +58,8 @@ struct RealVfsFile : public VfsFile {
31private: 58private:
32 bool Close(); 59 bool Close();
33 60
34 FileUtil::IOFile backing; 61 RealVfsFilesystem& base;
62 std::shared_ptr<FileUtil::IOFile> backing;
35 std::string path; 63 std::string path;
36 std::string parent_path; 64 std::string parent_path;
37 std::vector<std::string> path_components; 65 std::vector<std::string> path_components;
@@ -40,9 +68,12 @@ private:
40}; 68};
41 69
42// An implementation of VfsDirectory that represents a directory on the user's computer. 70// An implementation of VfsDirectory that represents a directory on the user's computer.
43struct RealVfsDirectory : public VfsDirectory { 71class RealVfsDirectory : public VfsDirectory {
44 RealVfsDirectory(const std::string& path, Mode perms = Mode::Read); 72 friend class RealVfsFilesystem;
73
74 RealVfsDirectory(RealVfsFilesystem& base, const std::string& path, Mode perms = Mode::Read);
45 75
76public:
46 std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; 77 std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
47 std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; 78 std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
48 bool IsWritable() const override; 79 bool IsWritable() const override;
@@ -60,6 +91,7 @@ protected:
60 bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; 91 bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
61 92
62private: 93private:
94 RealVfsFilesystem& base;
63 std::string path; 95 std::string path;
64 std::string parent_path; 96 std::string parent_path;
65 std::vector<std::string> path_components; 97 std::vector<std::string> path_components;