summaryrefslogtreecommitdiff
path: root/src/core/file_sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/file_sys')
-rw-r--r--src/core/file_sys/bis_factory.cpp4
-rw-r--r--src/core/file_sys/mode.h8
-rw-r--r--src/core/file_sys/partition_filesystem.cpp1
-rw-r--r--src/core/file_sys/patch_manager.cpp1
-rw-r--r--src/core/file_sys/registered_cache.cpp2
-rw-r--r--src/core/file_sys/vfs.cpp8
-rw-r--r--src/core/file_sys/vfs_libzip.cpp1
-rw-r--r--src/core/file_sys/vfs_real.cpp245
-rw-r--r--src/core/file_sys/vfs_real.h4
-rw-r--r--src/core/file_sys/xts_archive.cpp2
10 files changed, 136 insertions, 140 deletions
diff --git a/src/core/file_sys/bis_factory.cpp b/src/core/file_sys/bis_factory.cpp
index 7c6304ff0..f3891acf1 100644
--- a/src/core/file_sys/bis_factory.cpp
+++ b/src/core/file_sys/bis_factory.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <fmt/format.h> 5#include <fmt/format.h>
6#include "common/file_util.h" 6#include "common/fs/path_util.h"
7#include "core/file_sys/bis_factory.h" 7#include "core/file_sys/bis_factory.h"
8#include "core/file_sys/mode.h" 8#include "core/file_sys/mode.h"
9#include "core/file_sys/registered_cache.h" 9#include "core/file_sys/registered_cache.h"
@@ -85,7 +85,7 @@ VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id,
85 VirtualFilesystem file_system) const { 85 VirtualFilesystem file_system) const {
86 auto& keys = Core::Crypto::KeyManager::Instance(); 86 auto& keys = Core::Crypto::KeyManager::Instance();
87 Core::Crypto::PartitionDataManager pdm{file_system->OpenDirectory( 87 Core::Crypto::PartitionDataManager pdm{file_system->OpenDirectory(
88 Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), Mode::Read)}; 88 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir), Mode::Read)};
89 keys.PopulateFromPartitionData(pdm); 89 keys.PopulateFromPartitionData(pdm);
90 90
91 switch (id) { 91 switch (id) {
diff --git a/src/core/file_sys/mode.h b/src/core/file_sys/mode.h
index 2b4f21073..6c49a64e2 100644
--- a/src/core/file_sys/mode.h
+++ b/src/core/file_sys/mode.h
@@ -10,11 +10,13 @@
10namespace FileSys { 10namespace FileSys {
11 11
12enum class Mode : u32 { 12enum class Mode : u32 {
13 Read = 1, 13 Read = 1 << 0,
14 Write = 2, 14 Write = 1 << 1,
15 ReadWrite = Read | Write, 15 ReadWrite = Read | Write,
16 Append = 4, 16 Append = 1 << 2,
17 ReadAppend = Read | Append,
17 WriteAppend = Write | Append, 18 WriteAppend = Write | Append,
19 All = ReadWrite | Append,
18}; 20};
19 21
20DECLARE_ENUM_FLAG_OPERATORS(Mode) 22DECLARE_ENUM_FLAG_OPERATORS(Mode)
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
index 48a2ed4d4..c5967049e 100644
--- a/src/core/file_sys/partition_filesystem.cpp
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -8,7 +8,6 @@
8#include <iterator> 8#include <iterator>
9#include <utility> 9#include <utility>
10 10
11#include "common/file_util.h"
12#include "common/logging/log.h" 11#include "common/logging/log.h"
13#include "core/file_sys/partition_filesystem.h" 12#include "core/file_sys/partition_filesystem.h"
14#include "core/file_sys/vfs_offset.h" 13#include "core/file_sys/vfs_offset.h"
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index cc9b4b637..53b8b7ca0 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -7,7 +7,6 @@
7#include <cstddef> 7#include <cstddef>
8#include <cstring> 8#include <cstring>
9 9
10#include "common/file_util.h"
11#include "common/hex_util.h" 10#include "common/hex_util.h"
12#include "common/logging/log.h" 11#include "common/logging/log.h"
13#include "common/settings.h" 12#include "common/settings.h"
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index b0cb65952..066c6789a 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -7,7 +7,7 @@
7#include <regex> 7#include <regex>
8#include <mbedtls/sha256.h> 8#include <mbedtls/sha256.h>
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/file_util.h" 10#include "common/fs/path_util.h"
11#include "common/hex_util.h" 11#include "common/hex_util.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "core/crypto/key_manager.h" 13#include "core/crypto/key_manager.h"
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index f497e9396..215e1cb1a 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -5,8 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6#include <numeric> 6#include <numeric>
7#include <string> 7#include <string>
8#include "common/common_paths.h" 8#include "common/fs/path_util.h"
9#include "common/file_util.h"
10#include "common/logging/backend.h" 9#include "common/logging/backend.h"
11#include "core/file_sys/mode.h" 10#include "core/file_sys/mode.h"
12#include "core/file_sys/vfs.h" 11#include "core/file_sys/vfs.h"
@@ -122,15 +121,14 @@ VirtualDir VfsFilesystem::CopyDirectory(std::string_view old_path_, std::string_
122 return nullptr; 121 return nullptr;
123 122
124 for (const auto& file : old_dir->GetFiles()) { 123 for (const auto& file : old_dir->GetFiles()) {
125 const auto x = 124 const auto x = CopyFile(old_path + '/' + file->GetName(), new_path + '/' + file->GetName());
126 CopyFile(old_path + DIR_SEP + file->GetName(), new_path + DIR_SEP + file->GetName());
127 if (x == nullptr) 125 if (x == nullptr)
128 return nullptr; 126 return nullptr;
129 } 127 }
130 128
131 for (const auto& dir : old_dir->GetSubdirectories()) { 129 for (const auto& dir : old_dir->GetSubdirectories()) {
132 const auto x = 130 const auto x =
133 CopyDirectory(old_path + DIR_SEP + dir->GetName(), new_path + DIR_SEP + dir->GetName()); 131 CopyDirectory(old_path + '/' + dir->GetName(), new_path + '/' + dir->GetName());
134 if (x == nullptr) 132 if (x == nullptr)
135 return nullptr; 133 return nullptr;
136 } 134 }
diff --git a/src/core/file_sys/vfs_libzip.cpp b/src/core/file_sys/vfs_libzip.cpp
index 618eb658a..cd162c0c3 100644
--- a/src/core/file_sys/vfs_libzip.cpp
+++ b/src/core/file_sys/vfs_libzip.cpp
@@ -13,6 +13,7 @@
13#pragma GCC diagnostic pop 13#pragma GCC diagnostic pop
14#endif 14#endif
15 15
16#include "common/fs/path_util.h"
16#include "common/logging/backend.h" 17#include "common/logging/backend.h"
17#include "core/file_sys/vfs.h" 18#include "core/file_sys/vfs.h"
18#include "core/file_sys/vfs_libzip.h" 19#include "core/file_sys/vfs_libzip.h"
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 3d89dd644..d0b8fd046 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -7,8 +7,9 @@
7#include <iterator> 7#include <iterator>
8#include <utility> 8#include <utility>
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/common_paths.h" 10#include "common/fs/file.h"
11#include "common/file_util.h" 11#include "common/fs/fs.h"
12#include "common/fs/path_util.h"
12#include "common/logging/log.h" 13#include "common/logging/log.h"
13#include "core/file_sys/vfs_real.h" 14#include "core/file_sys/vfs_real.h"
14 15
@@ -16,33 +17,31 @@ namespace FileSys {
16 17
17namespace FS = Common::FS; 18namespace FS = Common::FS;
18 19
19static std::string ModeFlagsToString(Mode mode) { 20namespace {
20 std::string mode_str; 21
21 22constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) {
22 // Calculate the correct open mode for the file. 23 switch (mode) {
23 if (True(mode & Mode::Read) && True(mode & Mode::Write)) { 24 case Mode::Read:
24 if (True(mode & Mode::Append)) { 25 return FS::FileAccessMode::Read;
25 mode_str = "a+"; 26 case Mode::Write:
26 } else { 27 return FS::FileAccessMode::Write;
27 mode_str = "r+"; 28 case Mode::ReadWrite:
28 } 29 return FS::FileAccessMode::ReadWrite;
29 } else { 30 case Mode::Append:
30 if (True(mode & Mode::Read)) { 31 return FS::FileAccessMode::Append;
31 mode_str = "r"; 32 case Mode::ReadAppend:
32 } else if (True(mode & Mode::Append)) { 33 return FS::FileAccessMode::ReadAppend;
33 mode_str = "a"; 34 case Mode::WriteAppend:
34 } else if (True(mode & Mode::Write)) { 35 return FS::FileAccessMode::Append;
35 mode_str = "w"; 36 case Mode::All:
36 } else { 37 return FS::FileAccessMode::ReadAppend;
37 UNREACHABLE_MSG("Invalid file open mode: {:02X}", static_cast<u8>(mode)); 38 default:
38 } 39 return {};
39 } 40 }
40
41 mode_str += "b";
42
43 return mode_str;
44} 41}
45 42
43} // Anonymous namespace
44
46RealVfsFilesystem::RealVfsFilesystem() : VfsFilesystem(nullptr) {} 45RealVfsFilesystem::RealVfsFilesystem() : VfsFilesystem(nullptr) {}
47RealVfsFilesystem::~RealVfsFilesystem() = default; 46RealVfsFilesystem::~RealVfsFilesystem() = default;
48 47
@@ -63,7 +62,7 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
63 if (!FS::Exists(path)) { 62 if (!FS::Exists(path)) {
64 return VfsEntryType::None; 63 return VfsEntryType::None;
65 } 64 }
66 if (FS::IsDirectory(path)) { 65 if (FS::IsDir(path)) {
67 return VfsEntryType::Directory; 66 return VfsEntryType::Directory;
68 } 67 }
69 68
@@ -81,12 +80,13 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
81 } 80 }
82 } 81 }
83 82
84 if (!FS::Exists(path) && True(perms & Mode::WriteAppend)) { 83 auto backing = FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile);
85 FS::CreateEmptyFile(path); 84
85 if (!backing) {
86 return nullptr;
86 } 87 }
87 88
88 auto backing = std::make_shared<FS::IOFile>(path, ModeFlagsToString(perms).c_str()); 89 cache.insert_or_assign(path, std::move(backing));
89 cache.insert_or_assign(path, backing);
90 90
91 // Cannot use make_shared as RealVfsFile constructor is private 91 // Cannot use make_shared as RealVfsFile constructor is private
92 return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms)); 92 return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms));
@@ -94,25 +94,29 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
94 94
95VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { 95VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
96 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); 96 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
97 const auto path_fwd = FS::SanitizePath(path, FS::DirectorySeparator::ForwardSlash); 97 // Current usages of CreateFile expect to delete the contents of an existing file.
98 if (!FS::Exists(path)) { 98 if (FS::IsFile(path)) {
99 FS::CreateFullPath(path_fwd); 99 FS::IOFile temp{path, FS::FileAccessMode::Write, FS::FileType::BinaryFile};
100 if (!FS::CreateEmptyFile(path)) { 100
101 if (!temp.IsOpen()) {
101 return nullptr; 102 return nullptr;
102 } 103 }
104
105 temp.Close();
106
107 return OpenFile(path, perms);
108 }
109
110 if (!FS::NewFile(path)) {
111 return nullptr;
103 } 112 }
113
104 return OpenFile(path, perms); 114 return OpenFile(path, perms);
105} 115}
106 116
107VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) { 117VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) {
108 const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); 118 // Unused
109 const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); 119 return nullptr;
110
111 if (!FS::Exists(old_path) || FS::Exists(new_path) || FS::IsDirectory(old_path) ||
112 !FS::Copy(old_path, new_path)) {
113 return nullptr;
114 }
115 return OpenFile(new_path, Mode::ReadWrite);
116} 120}
117 121
118VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { 122VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {
@@ -127,13 +131,13 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
127 file->Close(); 131 file->Close();
128 } 132 }
129 133
130 if (!FS::Exists(old_path) || FS::Exists(new_path) || FS::IsDirectory(old_path) || 134 if (!FS::RenameFile(old_path, new_path)) {
131 !FS::Rename(old_path, new_path)) {
132 return nullptr; 135 return nullptr;
133 } 136 }
134 137
135 cache.erase(old_path); 138 cache.erase(old_path);
136 if (file->Open(new_path, "r+b")) { 139 file->Open(new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile);
140 if (file->IsOpen()) {
137 cache.insert_or_assign(new_path, std::move(file)); 141 cache.insert_or_assign(new_path, std::move(file));
138 } else { 142 } else {
139 LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", new_path); 143 LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", new_path);
@@ -157,7 +161,7 @@ bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
157 cache.erase(path); 161 cache.erase(path);
158 } 162 }
159 163
160 return FS::Delete(path); 164 return FS::RemoveFile(path);
161} 165}
162 166
163VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { 167VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) {
@@ -168,12 +172,8 @@ VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms)
168 172
169VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { 173VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) {
170 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); 174 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
171 const auto path_fwd = FS::SanitizePath(path, FS::DirectorySeparator::ForwardSlash); 175 if (!FS::CreateDirs(path)) {
172 if (!FS::Exists(path)) { 176 return nullptr;
173 FS::CreateFullPath(path_fwd);
174 if (!FS::CreateDir(path)) {
175 return nullptr;
176 }
177 } 177 }
178 // Cannot use make_shared as RealVfsDirectory constructor is private 178 // Cannot use make_shared as RealVfsDirectory constructor is private
179 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); 179 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
@@ -181,13 +181,8 @@ VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms
181 181
182VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_, 182VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_,
183 std::string_view new_path_) { 183 std::string_view new_path_) {
184 const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); 184 // Unused
185 const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); 185 return nullptr;
186 if (!FS::Exists(old_path) || FS::Exists(new_path) || !FS::IsDirectory(old_path)) {
187 return nullptr;
188 }
189 FS::CopyDir(old_path, new_path);
190 return OpenDirectory(new_path, Mode::ReadWrite);
191} 186}
192 187
193VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, 188VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
@@ -195,8 +190,7 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
195 const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); 190 const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault);
196 const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); 191 const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault);
197 192
198 if (!FS::Exists(old_path) || FS::Exists(new_path) || FS::IsDirectory(old_path) || 193 if (!FS::RenameDir(old_path, new_path)) {
199 !FS::Rename(old_path, new_path)) {
200 return nullptr; 194 return nullptr;
201 } 195 }
202 196
@@ -208,7 +202,7 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
208 202
209 const auto file_old_path = 203 const auto file_old_path =
210 FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault); 204 FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault);
211 auto file_new_path = FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()), 205 auto file_new_path = FS::SanitizePath(new_path + '/' + kv.first.substr(old_path.size()),
212 FS::DirectorySeparator::PlatformDefault); 206 FS::DirectorySeparator::PlatformDefault);
213 const auto& cached = cache[file_old_path]; 207 const auto& cached = cache[file_old_path];
214 208
@@ -218,7 +212,8 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
218 212
219 auto file = cached.lock(); 213 auto file = cached.lock();
220 cache.erase(file_old_path); 214 cache.erase(file_old_path);
221 if (file->Open(file_new_path, "r+b")) { 215 file->Open(file_new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile);
216 if (file->IsOpen()) {
222 cache.insert_or_assign(std::move(file_new_path), std::move(file)); 217 cache.insert_or_assign(std::move(file_new_path), std::move(file));
223 } else { 218 } else {
224 LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", file_new_path); 219 LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", file_new_path);
@@ -245,15 +240,13 @@ bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {
245 cache.erase(kv.first); 240 cache.erase(kv.first);
246 } 241 }
247 242
248 return FS::DeleteDirRecursively(path); 243 return FS::RemoveDirRecursively(path);
249} 244}
250 245
251RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FS::IOFile> backing_, 246RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FS::IOFile> backing_,
252 const std::string& path_, Mode perms_) 247 const std::string& path_, Mode perms_)
253 : base(base_), backing(std::move(backing_)), path(path_), parent_path(FS::GetParentPath(path_)), 248 : base(base_), backing(std::move(backing_)), path(path_), parent_path(FS::GetParentPath(path_)),
254 path_components(FS::SplitPathComponents(path_)), 249 path_components(FS::SplitPathComponents(path_)), perms(perms_) {}
255 parent_components(FS::SliceVector(path_components, 0, path_components.size() - 1)),
256 perms(perms_) {}
257 250
258RealVfsFile::~RealVfsFile() = default; 251RealVfsFile::~RealVfsFile() = default;
259 252
@@ -266,7 +259,7 @@ std::size_t RealVfsFile::GetSize() const {
266} 259}
267 260
268bool RealVfsFile::Resize(std::size_t new_size) { 261bool RealVfsFile::Resize(std::size_t new_size) {
269 return backing->Resize(new_size); 262 return backing->SetSize(new_size);
270} 263}
271 264
272VirtualDir RealVfsFile::GetContainingDirectory() const { 265VirtualDir RealVfsFile::GetContainingDirectory() const {
@@ -274,33 +267,33 @@ VirtualDir RealVfsFile::GetContainingDirectory() const {
274} 267}
275 268
276bool RealVfsFile::IsWritable() const { 269bool RealVfsFile::IsWritable() const {
277 return True(perms & Mode::WriteAppend); 270 return True(perms & Mode::Write);
278} 271}
279 272
280bool RealVfsFile::IsReadable() const { 273bool RealVfsFile::IsReadable() const {
281 return True(perms & Mode::ReadWrite); 274 return True(perms & Mode::Read);
282} 275}
283 276
284std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { 277std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const {
285 if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) { 278 if (!backing->Seek(static_cast<s64>(offset))) {
286 return 0; 279 return 0;
287 } 280 }
288 return backing->ReadBytes(data, length); 281 return backing->ReadSpan(std::span{data, length});
289} 282}
290 283
291std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { 284std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) {
292 if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) { 285 if (!backing->Seek(static_cast<s64>(offset))) {
293 return 0; 286 return 0;
294 } 287 }
295 return backing->WriteBytes(data, length); 288 return backing->WriteSpan(std::span{data, length});
296} 289}
297 290
298bool RealVfsFile::Rename(std::string_view name) { 291bool RealVfsFile::Rename(std::string_view name) {
299 return base.MoveFile(path, parent_path + DIR_SEP + std::string(name)) != nullptr; 292 return base.MoveFile(path, parent_path + '/' + std::string(name)) != nullptr;
300} 293}
301 294
302bool RealVfsFile::Close() { 295void RealVfsFile::Close() {
303 return backing->Close(); 296 backing->Close();
304} 297}
305 298
306// TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if 299// TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if
@@ -313,15 +306,16 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>(
313 } 306 }
314 307
315 std::vector<VirtualFile> out; 308 std::vector<VirtualFile> out;
316 FS::ForeachDirectoryEntry( 309
317 nullptr, path, 310 const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) {
318 [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { 311 const auto full_path_string = FS::PathToUTF8String(full_path);
319 const std::string full_path = directory + DIR_SEP + filename; 312
320 if (!FS::IsDirectory(full_path)) { 313 out.emplace_back(base.OpenFile(full_path_string, perms));
321 out.emplace_back(base.OpenFile(full_path, perms)); 314
322 } 315 return true;
323 return true; 316 };
324 }); 317
318 FS::IterateDirEntries(path, callback, FS::DirEntryFilter::File);
325 319
326 return out; 320 return out;
327} 321}
@@ -333,42 +327,41 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi
333 } 327 }
334 328
335 std::vector<VirtualDir> out; 329 std::vector<VirtualDir> out;
336 FS::ForeachDirectoryEntry( 330
337 nullptr, path, 331 const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) {
338 [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { 332 const auto full_path_string = FS::PathToUTF8String(full_path);
339 const std::string full_path = directory + DIR_SEP + filename; 333
340 if (FS::IsDirectory(full_path)) { 334 out.emplace_back(base.OpenDirectory(full_path_string, perms));
341 out.emplace_back(base.OpenDirectory(full_path, perms)); 335
342 } 336 return true;
343 return true; 337 };
344 }); 338
339 FS::IterateDirEntries(path, callback, FS::DirEntryFilter::Directory);
345 340
346 return out; 341 return out;
347} 342}
348 343
349RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_) 344RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_)
350 : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)), 345 : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)),
351 path_components(FS::SplitPathComponents(path)), 346 path_components(FS::SplitPathComponents(path)), perms(perms_) {
352 parent_components(FS::SliceVector(path_components, 0, path_components.size() - 1)), 347 if (!FS::Exists(path) && True(perms & Mode::Write)) {
353 perms(perms_) { 348 void(FS::CreateDirs(path));
354 if (!FS::Exists(path) && True(perms & Mode::WriteAppend)) {
355 FS::CreateDir(path);
356 } 349 }
357} 350}
358 351
359RealVfsDirectory::~RealVfsDirectory() = default; 352RealVfsDirectory::~RealVfsDirectory() = default;
360 353
361VirtualFile RealVfsDirectory::GetFileRelative(std::string_view relative_path) const { 354VirtualFile RealVfsDirectory::GetFileRelative(std::string_view relative_path) const {
362 const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); 355 const auto full_path = FS::SanitizePath(path + '/' + std::string(relative_path));
363 if (!FS::Exists(full_path) || FS::IsDirectory(full_path)) { 356 if (!FS::Exists(full_path) || FS::IsDir(full_path)) {
364 return nullptr; 357 return nullptr;
365 } 358 }
366 return base.OpenFile(full_path, perms); 359 return base.OpenFile(full_path, perms);
367} 360}
368 361
369VirtualDir RealVfsDirectory::GetDirectoryRelative(std::string_view relative_path) const { 362VirtualDir RealVfsDirectory::GetDirectoryRelative(std::string_view relative_path) const {
370 const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); 363 const auto full_path = FS::SanitizePath(path + '/' + std::string(relative_path));
371 if (!FS::Exists(full_path) || !FS::IsDirectory(full_path)) { 364 if (!FS::Exists(full_path) || !FS::IsDir(full_path)) {
372 return nullptr; 365 return nullptr;
373 } 366 }
374 return base.OpenDirectory(full_path, perms); 367 return base.OpenDirectory(full_path, perms);
@@ -383,17 +376,20 @@ VirtualDir RealVfsDirectory::GetSubdirectory(std::string_view name) const {
383} 376}
384 377
385VirtualFile RealVfsDirectory::CreateFileRelative(std::string_view relative_path) { 378VirtualFile RealVfsDirectory::CreateFileRelative(std::string_view relative_path) {
386 const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); 379 const auto full_path = FS::SanitizePath(path + '/' + std::string(relative_path));
380 if (!FS::CreateParentDirs(full_path)) {
381 return nullptr;
382 }
387 return base.CreateFile(full_path, perms); 383 return base.CreateFile(full_path, perms);
388} 384}
389 385
390VirtualDir RealVfsDirectory::CreateDirectoryRelative(std::string_view relative_path) { 386VirtualDir RealVfsDirectory::CreateDirectoryRelative(std::string_view relative_path) {
391 const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); 387 const auto full_path = FS::SanitizePath(path + '/' + std::string(relative_path));
392 return base.CreateDirectory(full_path, perms); 388 return base.CreateDirectory(full_path, perms);
393} 389}
394 390
395bool RealVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) { 391bool RealVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) {
396 const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(name)); 392 const auto full_path = FS::SanitizePath(this->path + '/' + std::string(name));
397 return base.DeleteDirectory(full_path); 393 return base.DeleteDirectory(full_path);
398} 394}
399 395
@@ -406,11 +402,11 @@ std::vector<VirtualDir> RealVfsDirectory::GetSubdirectories() const {
406} 402}
407 403
408bool RealVfsDirectory::IsWritable() const { 404bool RealVfsDirectory::IsWritable() const {
409 return True(perms & Mode::WriteAppend); 405 return True(perms & Mode::Write);
410} 406}
411 407
412bool RealVfsDirectory::IsReadable() const { 408bool RealVfsDirectory::IsReadable() const {
413 return True(perms & Mode::ReadWrite); 409 return True(perms & Mode::Read);
414} 410}
415 411
416std::string RealVfsDirectory::GetName() const { 412std::string RealVfsDirectory::GetName() const {
@@ -426,27 +422,27 @@ VirtualDir RealVfsDirectory::GetParentDirectory() const {
426} 422}
427 423
428VirtualDir RealVfsDirectory::CreateSubdirectory(std::string_view name) { 424VirtualDir RealVfsDirectory::CreateSubdirectory(std::string_view name) {
429 const std::string subdir_path = (path + DIR_SEP).append(name); 425 const std::string subdir_path = (path + '/').append(name);
430 return base.CreateDirectory(subdir_path, perms); 426 return base.CreateDirectory(subdir_path, perms);
431} 427}
432 428
433VirtualFile RealVfsDirectory::CreateFile(std::string_view name) { 429VirtualFile RealVfsDirectory::CreateFile(std::string_view name) {
434 const std::string file_path = (path + DIR_SEP).append(name); 430 const std::string file_path = (path + '/').append(name);
435 return base.CreateFile(file_path, perms); 431 return base.CreateFile(file_path, perms);
436} 432}
437 433
438bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) { 434bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) {
439 const std::string subdir_path = (path + DIR_SEP).append(name); 435 const std::string subdir_path = (path + '/').append(name);
440 return base.DeleteDirectory(subdir_path); 436 return base.DeleteDirectory(subdir_path);
441} 437}
442 438
443bool RealVfsDirectory::DeleteFile(std::string_view name) { 439bool RealVfsDirectory::DeleteFile(std::string_view name) {
444 const std::string file_path = (path + DIR_SEP).append(name); 440 const std::string file_path = (path + '/').append(name);
445 return base.DeleteFile(file_path); 441 return base.DeleteFile(file_path);
446} 442}
447 443
448bool RealVfsDirectory::Rename(std::string_view name) { 444bool RealVfsDirectory::Rename(std::string_view name) {
449 const std::string new_name = (parent_path + DIR_SEP).append(name); 445 const std::string new_name = (parent_path + '/').append(name);
450 return base.MoveFile(path, new_name) != nullptr; 446 return base.MoveFile(path, new_name) != nullptr;
451} 447}
452 448
@@ -462,14 +458,17 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries()
462 } 458 }
463 459
464 std::map<std::string, VfsEntryType, std::less<>> out; 460 std::map<std::string, VfsEntryType, std::less<>> out;
465 FS::ForeachDirectoryEntry( 461
466 nullptr, path, 462 const FS::DirEntryCallable callback = [&out](const std::filesystem::path& full_path) {
467 [&out](u64* entries_out, const std::string& directory, const std::string& filename) { 463 const auto filename = FS::PathToUTF8String(full_path.filename());
468 const std::string full_path = directory + DIR_SEP + filename; 464
469 out.emplace(filename, 465 out.insert_or_assign(filename,
470 FS::IsDirectory(full_path) ? VfsEntryType::Directory : VfsEntryType::File); 466 FS::IsDir(full_path) ? VfsEntryType::Directory : VfsEntryType::File);
471 return true; 467
472 }); 468 return true;
469 };
470
471 FS::IterateDirEntries(path, callback);
473 472
474 return out; 473 return out;
475} 474}
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index 0666f2679..e4d1bba79 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -61,14 +61,13 @@ private:
61 RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<Common::FS::IOFile> backing, 61 RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<Common::FS::IOFile> backing,
62 const std::string& path, Mode perms = Mode::Read); 62 const std::string& path, Mode perms = Mode::Read);
63 63
64 bool Close(); 64 void Close();
65 65
66 RealVfsFilesystem& base; 66 RealVfsFilesystem& base;
67 std::shared_ptr<Common::FS::IOFile> backing; 67 std::shared_ptr<Common::FS::IOFile> backing;
68 std::string path; 68 std::string path;
69 std::string parent_path; 69 std::string parent_path;
70 std::vector<std::string> path_components; 70 std::vector<std::string> path_components;
71 std::vector<std::string> parent_components;
72 Mode perms; 71 Mode perms;
73}; 72};
74 73
@@ -110,7 +109,6 @@ private:
110 std::string path; 109 std::string path;
111 std::string parent_path; 110 std::string parent_path;
112 std::vector<std::string> path_components; 111 std::vector<std::string> path_components;
113 std::vector<std::string> parent_components;
114 Mode perms; 112 Mode perms;
115}; 113};
116 114
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index 814fd5680..d6fe1af47 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -11,7 +11,7 @@
11#include <mbedtls/md.h> 11#include <mbedtls/md.h>
12#include <mbedtls/sha256.h> 12#include <mbedtls/sha256.h>
13 13
14#include "common/file_util.h" 14#include "common/fs/path_util.h"
15#include "common/hex_util.h" 15#include "common/hex_util.h"
16#include "common/string_util.h" 16#include "common/string_util.h"
17#include "core/crypto/aes_util.h" 17#include "core/crypto/aes_util.h"