summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/file_sys/vfs.cpp148
-rw-r--r--src/core/file_sys/vfs.h66
2 files changed, 211 insertions, 3 deletions
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index dae1c16ef..24e158962 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -4,12 +4,160 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <numeric> 6#include <numeric>
7#include <string>
8#include "common/common_paths.h"
7#include "common/file_util.h" 9#include "common/file_util.h"
8#include "common/logging/backend.h" 10#include "common/logging/backend.h"
9#include "core/file_sys/vfs.h" 11#include "core/file_sys/vfs.h"
10 12
11namespace FileSys { 13namespace FileSys {
12 14
15VfsFilesystem::VfsFilesystem(VirtualDir root_) : root(std::move(root_)) {}
16
17VfsFilesystem::~VfsFilesystem() = default;
18
19std::string VfsFilesystem::GetName() const {
20 return root->GetName();
21}
22
23bool VfsFilesystem::IsReadable() const {
24 return root->IsReadable();
25}
26
27bool VfsFilesystem::IsWritable() const {
28 return root->IsWritable();
29}
30
31VfsEntryType VfsFilesystem::GetEntryType(std::string_view path_) const {
32 const auto path = FileUtil::SanitizePath(path_);
33 if (root->GetFileRelative(path) != nullptr)
34 return VfsEntryType::File;
35 if (root->GetDirectoryRelative(path) != nullptr)
36 return VfsEntryType::Directory;
37
38 return VfsEntryType::None;
39}
40
41VirtualFile VfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
42 const auto path = FileUtil::SanitizePath(path_);
43 return root->GetFileRelative(path);
44}
45
46VirtualFile VfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
47 const auto path = FileUtil::SanitizePath(path_);
48 return root->CreateFileRelative(path);
49}
50
51VirtualFile VfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) {
52 const auto old_path = FileUtil::SanitizePath(old_path_);
53 const auto new_path = FileUtil::SanitizePath(new_path_);
54
55 // VfsDirectory impls are only required to implement copy across the current directory.
56 if (FileUtil::GetParentPath(old_path) == FileUtil::GetParentPath(new_path)) {
57 if (!root->Copy(FileUtil::GetFilename(old_path), FileUtil::GetFilename(new_path)))
58 return nullptr;
59 return OpenFile(new_path, Mode::ReadWrite);
60 }
61
62 // Do it using RawCopy. Non-default impls are encouraged to optimize this.
63 const auto old_file = OpenFile(old_path, Mode::Read);
64 if (old_file == nullptr)
65 return nullptr;
66 auto new_file = OpenFile(new_path, Mode::Read);
67 if (new_file != nullptr)
68 return nullptr;
69 new_file = CreateFile(new_path, Mode::Write);
70 if (new_file == nullptr)
71 return nullptr;
72 if (!VfsRawCopy(old_file, new_file))
73 return nullptr;
74 return new_file;
75}
76
77VirtualFile VfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {
78 const auto old_path = FileUtil::SanitizePath(old_path_);
79 const auto new_path = FileUtil::SanitizePath(new_path_);
80
81 // Again, non-default impls are highly encouraged to provide a more optimized version of this.
82 auto out = CopyFile(old_path_, new_path_);
83 if (out == nullptr)
84 return nullptr;
85 if (DeleteFile(old_path))
86 return out;
87 return nullptr;
88}
89
90bool VfsFilesystem::DeleteFile(std::string_view path_) {
91 const auto path = FileUtil::SanitizePath(path_);
92 auto parent = OpenDirectory(FileUtil::GetParentPath(path), Mode::Write);
93 if (parent == nullptr)
94 return false;
95 return parent->DeleteFile(FileUtil::GetFilename(path));
96}
97
98VirtualDir VfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) {
99 const auto path = FileUtil::SanitizePath(path_);
100 return root->GetDirectoryRelative(path);
101}
102
103VirtualDir VfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) {
104 const auto path = FileUtil::SanitizePath(path_);
105 return root->CreateDirectoryRelative(path);
106}
107
108VirtualDir VfsFilesystem::CopyDirectory(std::string_view old_path_, std::string_view new_path_) {
109 const auto old_path = FileUtil::SanitizePath(old_path_);
110 const auto new_path = FileUtil::SanitizePath(new_path_);
111
112 // Non-default impls are highly encouraged to provide a more optimized version of this.
113 auto old_dir = OpenDirectory(old_path, Mode::Read);
114 if (old_dir == nullptr)
115 return nullptr;
116 auto new_dir = OpenDirectory(new_path, Mode::Read);
117 if (new_dir != nullptr)
118 return nullptr;
119 new_dir = CreateDirectory(new_path, Mode::Write);
120 if (new_dir == nullptr)
121 return nullptr;
122
123 for (const auto& file : old_dir->GetFiles()) {
124 const auto x =
125 CopyFile(old_path + DIR_SEP + file->GetName(), new_path + DIR_SEP + file->GetName());
126 if (x == nullptr)
127 return nullptr;
128 }
129
130 for (const auto& dir : old_dir->GetSubdirectories()) {
131 const auto x =
132 CopyDirectory(old_path + DIR_SEP + dir->GetName(), new_path + DIR_SEP + dir->GetName());
133 if (x == nullptr)
134 return nullptr;
135 }
136
137 return new_dir;
138}
139
140VirtualDir VfsFilesystem::MoveDirectory(std::string_view old_path_, std::string_view new_path_) {
141 const auto old_path = FileUtil::SanitizePath(old_path_);
142 const auto new_path = FileUtil::SanitizePath(new_path_);
143
144 // Non-default impls are highly encouraged to provide a more optimized version of this.
145 auto out = CopyDirectory(old_path_, new_path_);
146 if (out == nullptr)
147 return nullptr;
148 if (DeleteDirectory(old_path))
149 return out;
150 return nullptr;
151}
152
153bool VfsFilesystem::DeleteDirectory(std::string_view path_) {
154 const auto path = FileUtil::SanitizePath(path_);
155 auto parent = OpenDirectory(FileUtil::GetParentPath(path), Mode::Write);
156 if (parent == nullptr)
157 return false;
158 return parent->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path));
159}
160
13VfsFile::~VfsFile() = default; 161VfsFile::~VfsFile() = default;
14 162
15std::string VfsFile::GetExtension() const { 163std::string VfsFile::GetExtension() const {
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index fab9e2b45..9c7ef93b8 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -11,14 +11,74 @@
11#include <vector> 11#include <vector>
12#include "boost/optional.hpp" 12#include "boost/optional.hpp"
13#include "common/common_types.h" 13#include "common/common_types.h"
14#include "core/file_sys/mode.h"
14 15
15namespace FileSys { 16namespace FileSys {
17
18struct VfsFilesystem;
16struct VfsFile; 19struct VfsFile;
17struct VfsDirectory; 20struct VfsDirectory;
18 21
19// Convenience typedefs to use VfsDirectory and VfsFile 22// Convenience typedefs to use Vfs* interfaces
20using VirtualDir = std::shared_ptr<FileSys::VfsDirectory>; 23using VirtualFilesystem = std::shared_ptr<VfsFilesystem>;
21using VirtualFile = std::shared_ptr<FileSys::VfsFile>; 24using VirtualDir = std::shared_ptr<VfsDirectory>;
25using VirtualFile = std::shared_ptr<VfsFile>;
26
27// An enumeration representing what can be at the end of a path in a VfsFilesystem
28enum class VfsEntryType {
29 None,
30 File,
31 Directory,
32};
33
34// A class represnting an abstract filesystem. A default implementation given the root VirtualDir is
35// provided for convenience, but if the Vfs implementation has any additional state or
36// functionality, they will need to override.
37struct VfsFilesystem : NonCopyable {
38 VfsFilesystem(VirtualDir root);
39 virtual ~VfsFilesystem();
40
41 // Gets the friendly name for the filesystem.
42 virtual std::string GetName() const;
43
44 // Return whether or not the user has read permissions on this filesystem.
45 virtual bool IsReadable() const;
46 // Return whether or not the user has write permission on this filesystem.
47 virtual bool IsWritable() const;
48
49 // Determine if the entry at path is non-existant, a file, or a directory.
50 virtual VfsEntryType GetEntryType(std::string_view path) const;
51
52 // Opens the file with path relative to root. If it doesn't exist, returns nullptr.
53 virtual VirtualFile OpenFile(std::string_view path, Mode perms);
54 // Creates a new, empty file at path
55 virtual VirtualFile CreateFile(std::string_view path, Mode perms);
56 // Copies the file from old_path to new_path, returning the new file on success and nullptr on
57 // failure.
58 virtual VirtualFile CopyFile(std::string_view old_path, std::string_view new_path);
59 // Moves the file from old_path to new_path, returning the moved file on success and nullptr on
60 // failure.
61 virtual VirtualFile MoveFile(std::string_view old_path, std::string_view new_path);
62 // Deletes the file with path relative to root, returing true on success.
63 virtual bool DeleteFile(std::string_view path);
64
65 // Opens the directory with path relative to root. If it doesn't exist, returns nullptr.
66 virtual VirtualDir OpenDirectory(std::string_view path, Mode perms);
67 // Creates a new, empty directory at path
68 virtual VirtualDir CreateDirectory(std::string_view path, Mode perms);
69 // Copies the directory from old_path to new_path, returning the new directory on success and
70 // nullptr on failure.
71 virtual VirtualDir CopyDirectory(std::string_view old_path, std::string_view new_path);
72 // Moves the directory from old_path to new_path, returning the moved directory on success and
73 // nullptr on failure.
74 virtual VirtualDir MoveDirectory(std::string_view old_path, std::string_view new_path);
75 // Deletes the directory with path relative to root, returing true on success.
76 virtual bool DeleteDirectory(std::string_view path);
77
78protected:
79 // Root directory in default implementation.
80 VirtualDir root;
81};
22 82
23// A class representing a file in an abstract filesystem. 83// A class representing a file in an abstract filesystem.
24struct VfsFile : NonCopyable { 84struct VfsFile : NonCopyable {