diff options
| author | 2023-07-01 15:01:11 -0700 | |
|---|---|---|
| committer | 2023-07-01 15:01:11 -0700 | |
| commit | 98685d48e3cb9f25f6919f004ec62cadf33afad2 (patch) | |
| tree | 9df2ce7f57370641589bfae7196c77b090bcbe0f /src/core/file_sys | |
| parent | PR feedback + constification (diff) | |
| parent | Update translations (2023-07-01) (#10972) (diff) | |
| download | yuzu-98685d48e3cb9f25f6919f004ec62cadf33afad2.tar.gz yuzu-98685d48e3cb9f25f6919f004ec62cadf33afad2.tar.xz yuzu-98685d48e3cb9f25f6919f004ec62cadf33afad2.zip | |
Merge remote-tracking branch 'origin/master' into ssl
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 9 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_concat.cpp | 14 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.cpp | 101 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.h | 22 |
4 files changed, 95 insertions, 51 deletions
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 4e61d4335..d3286b352 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -153,7 +153,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 153 | const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); | 153 | const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); |
| 154 | 154 | ||
| 155 | std::vector<VirtualDir> patch_dirs = {sdmc_load_dir}; | 155 | std::vector<VirtualDir> patch_dirs = {sdmc_load_dir}; |
| 156 | if (load_dir != nullptr && load_dir->GetSize() > 0) { | 156 | if (load_dir != nullptr) { |
| 157 | const auto load_patch_dirs = load_dir->GetSubdirectories(); | 157 | const auto load_patch_dirs = load_dir->GetSubdirectories(); |
| 158 | patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end()); | 158 | patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end()); |
| 159 | } | 159 | } |
| @@ -354,8 +354,7 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t | |||
| 354 | const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); | 354 | const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 355 | const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); | 355 | const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); |
| 356 | if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || | 356 | if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || |
| 357 | ((load_dir == nullptr || load_dir->GetSize() <= 0) && | 357 | (load_dir == nullptr && sdmc_load_dir == nullptr)) { |
| 358 | (sdmc_load_dir == nullptr || sdmc_load_dir->GetSize() <= 0))) { | ||
| 359 | return; | 358 | return; |
| 360 | } | 359 | } |
| 361 | 360 | ||
| @@ -496,7 +495,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 496 | 495 | ||
| 497 | // General Mods (LayeredFS and IPS) | 496 | // General Mods (LayeredFS and IPS) |
| 498 | const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id); | 497 | const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 499 | if (mod_dir != nullptr && mod_dir->GetSize() > 0) { | 498 | if (mod_dir != nullptr) { |
| 500 | for (const auto& mod : mod_dir->GetSubdirectories()) { | 499 | for (const auto& mod : mod_dir->GetSubdirectories()) { |
| 501 | std::string types; | 500 | std::string types; |
| 502 | 501 | ||
| @@ -540,7 +539,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 540 | 539 | ||
| 541 | // SDMC mod directory (RomFS LayeredFS) | 540 | // SDMC mod directory (RomFS LayeredFS) |
| 542 | const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); | 541 | const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); |
| 543 | if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0) { | 542 | if (sdmc_mod_dir != nullptr) { |
| 544 | std::string types; | 543 | std::string types; |
| 545 | if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"))) { | 544 | if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"))) { |
| 546 | AppendCommaIfNotEmpty(types, "LayeredExeFS"); | 545 | AppendCommaIfNotEmpty(types, "LayeredExeFS"); |
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index 853b893a1..311a59e5f 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp | |||
| @@ -150,23 +150,29 @@ std::size_t ConcatenatedVfsFile::Read(u8* data, std::size_t length, std::size_t | |||
| 150 | while (cur_length > 0 && it != concatenation_map.end()) { | 150 | while (cur_length > 0 && it != concatenation_map.end()) { |
| 151 | // Check if we can read the file at this position. | 151 | // Check if we can read the file at this position. |
| 152 | const auto& file = it->file; | 152 | const auto& file = it->file; |
| 153 | const u64 file_offset = it->offset; | 153 | const u64 map_offset = it->offset; |
| 154 | const u64 file_size = file->GetSize(); | 154 | const u64 file_size = file->GetSize(); |
| 155 | 155 | ||
| 156 | if (cur_offset >= file_offset + file_size) { | 156 | if (cur_offset > map_offset + file_size) { |
| 157 | // Entirely out of bounds read. | 157 | // Entirely out of bounds read. |
| 158 | break; | 158 | break; |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | // Read the file at this position. | 161 | // Read the file at this position. |
| 162 | const u64 intended_read_size = std::min<u64>(cur_length, file_size); | 162 | const u64 file_seek = cur_offset - map_offset; |
| 163 | const u64 intended_read_size = std::min<u64>(cur_length, file_size - file_seek); | ||
| 163 | const u64 actual_read_size = | 164 | const u64 actual_read_size = |
| 164 | file->Read(data + (cur_offset - offset), intended_read_size, cur_offset - file_offset); | 165 | file->Read(data + (cur_offset - offset), intended_read_size, file_seek); |
| 165 | 166 | ||
| 166 | // Update tracking. | 167 | // Update tracking. |
| 167 | cur_offset += actual_read_size; | 168 | cur_offset += actual_read_size; |
| 168 | cur_length -= actual_read_size; | 169 | cur_length -= actual_read_size; |
| 169 | it++; | 170 | it++; |
| 171 | |||
| 172 | // If we encountered a short read, we're done. | ||
| 173 | if (actual_read_size < intended_read_size) { | ||
| 174 | break; | ||
| 175 | } | ||
| 170 | } | 176 | } |
| 171 | 177 | ||
| 172 | return cur_offset - offset; | 178 | return cur_offset - offset; |
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 7a15d8438..b0515ec05 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/fs/fs.h" | 10 | #include "common/fs/fs.h" |
| 11 | #include "common/fs/path_util.h" | 11 | #include "common/fs/path_util.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "core/file_sys/vfs.h" | ||
| 13 | #include "core/file_sys/vfs_real.h" | 14 | #include "core/file_sys/vfs_real.h" |
| 14 | 15 | ||
| 15 | // For FileTimeStampRaw | 16 | // For FileTimeStampRaw |
| @@ -72,8 +73,10 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const { | |||
| 72 | return VfsEntryType::File; | 73 | return VfsEntryType::File; |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | 76 | VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size, |
| 77 | Mode perms) { | ||
| 76 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 78 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 79 | std::scoped_lock lk{list_lock}; | ||
| 77 | 80 | ||
| 78 | if (auto it = cache.find(path); it != cache.end()) { | 81 | if (auto it = cache.find(path); it != cache.end()) { |
| 79 | if (auto file = it->second.lock(); file) { | 82 | if (auto file = it->second.lock(); file) { |
| @@ -81,23 +84,30 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | |||
| 81 | } | 84 | } |
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | if (!FS::Exists(path) || !FS::IsFile(path)) { | 87 | if (!size && !FS::IsFile(path)) { |
| 85 | return nullptr; | 88 | return nullptr; |
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | auto reference = std::make_unique<FileReference>(); | 91 | auto reference = std::make_unique<FileReference>(); |
| 89 | this->InsertReferenceIntoList(*reference); | 92 | this->InsertReferenceIntoListLocked(*reference); |
| 90 | 93 | ||
| 91 | auto file = | 94 | auto file = std::shared_ptr<RealVfsFile>( |
| 92 | std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, std::move(reference), path, perms)); | 95 | new RealVfsFile(*this, std::move(reference), path, perms, size)); |
| 93 | cache[path] = file; | 96 | cache[path] = file; |
| 94 | 97 | ||
| 95 | return file; | 98 | return file; |
| 96 | } | 99 | } |
| 97 | 100 | ||
| 101 | VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | ||
| 102 | return OpenFileFromEntry(path_, {}, perms); | ||
| 103 | } | ||
| 104 | |||
| 98 | VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { | 105 | VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { |
| 99 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 106 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 100 | cache.erase(path); | 107 | { |
| 108 | std::scoped_lock lk{list_lock}; | ||
| 109 | cache.erase(path); | ||
| 110 | } | ||
| 101 | 111 | ||
| 102 | // Current usages of CreateFile expect to delete the contents of an existing file. | 112 | // Current usages of CreateFile expect to delete the contents of an existing file. |
| 103 | if (FS::IsFile(path)) { | 113 | if (FS::IsFile(path)) { |
| @@ -127,8 +137,11 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_ | |||
| 127 | VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { | 137 | VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { |
| 128 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); | 138 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); |
| 129 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); | 139 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); |
| 130 | cache.erase(old_path); | 140 | { |
| 131 | cache.erase(new_path); | 141 | std::scoped_lock lk{list_lock}; |
| 142 | cache.erase(old_path); | ||
| 143 | cache.erase(new_path); | ||
| 144 | } | ||
| 132 | if (!FS::RenameFile(old_path, new_path)) { | 145 | if (!FS::RenameFile(old_path, new_path)) { |
| 133 | return nullptr; | 146 | return nullptr; |
| 134 | } | 147 | } |
| @@ -137,7 +150,10 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_ | |||
| 137 | 150 | ||
| 138 | bool RealVfsFilesystem::DeleteFile(std::string_view path_) { | 151 | bool RealVfsFilesystem::DeleteFile(std::string_view path_) { |
| 139 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 152 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 140 | cache.erase(path); | 153 | { |
| 154 | std::scoped_lock lk{list_lock}; | ||
| 155 | cache.erase(path); | ||
| 156 | } | ||
| 141 | return FS::RemoveFile(path); | 157 | return FS::RemoveFile(path); |
| 142 | } | 158 | } |
| 143 | 159 | ||
| @@ -176,14 +192,17 @@ bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { | |||
| 176 | return FS::RemoveDirRecursively(path); | 192 | return FS::RemoveDirRecursively(path); |
| 177 | } | 193 | } |
| 178 | 194 | ||
| 179 | void RealVfsFilesystem::RefreshReference(const std::string& path, Mode perms, | 195 | std::unique_lock<std::mutex> RealVfsFilesystem::RefreshReference(const std::string& path, |
| 180 | FileReference& reference) { | 196 | Mode perms, |
| 197 | FileReference& reference) { | ||
| 198 | std::unique_lock lk{list_lock}; | ||
| 199 | |||
| 181 | // Temporarily remove from list. | 200 | // Temporarily remove from list. |
| 182 | this->RemoveReferenceFromList(reference); | 201 | this->RemoveReferenceFromListLocked(reference); |
| 183 | 202 | ||
| 184 | // Restore file if needed. | 203 | // Restore file if needed. |
| 185 | if (!reference.file) { | 204 | if (!reference.file) { |
| 186 | this->EvictSingleReference(); | 205 | this->EvictSingleReferenceLocked(); |
| 187 | 206 | ||
| 188 | reference.file = | 207 | reference.file = |
| 189 | FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); | 208 | FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); |
| @@ -193,12 +212,16 @@ void RealVfsFilesystem::RefreshReference(const std::string& path, Mode perms, | |||
| 193 | } | 212 | } |
| 194 | 213 | ||
| 195 | // Reinsert into list. | 214 | // Reinsert into list. |
| 196 | this->InsertReferenceIntoList(reference); | 215 | this->InsertReferenceIntoListLocked(reference); |
| 216 | |||
| 217 | return lk; | ||
| 197 | } | 218 | } |
| 198 | 219 | ||
| 199 | void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference) { | 220 | void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference) { |
| 221 | std::scoped_lock lk{list_lock}; | ||
| 222 | |||
| 200 | // Remove from list. | 223 | // Remove from list. |
| 201 | this->RemoveReferenceFromList(*reference); | 224 | this->RemoveReferenceFromListLocked(*reference); |
| 202 | 225 | ||
| 203 | // Close the file. | 226 | // Close the file. |
| 204 | if (reference->file) { | 227 | if (reference->file) { |
| @@ -207,14 +230,14 @@ void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference | |||
| 207 | } | 230 | } |
| 208 | } | 231 | } |
| 209 | 232 | ||
| 210 | void RealVfsFilesystem::EvictSingleReference() { | 233 | void RealVfsFilesystem::EvictSingleReferenceLocked() { |
| 211 | if (num_open_files < MaxOpenFiles || open_references.empty()) { | 234 | if (num_open_files < MaxOpenFiles || open_references.empty()) { |
| 212 | return; | 235 | return; |
| 213 | } | 236 | } |
| 214 | 237 | ||
| 215 | // Get and remove from list. | 238 | // Get and remove from list. |
| 216 | auto& reference = open_references.back(); | 239 | auto& reference = open_references.back(); |
| 217 | this->RemoveReferenceFromList(reference); | 240 | this->RemoveReferenceFromListLocked(reference); |
| 218 | 241 | ||
| 219 | // Close the file. | 242 | // Close the file. |
| 220 | if (reference.file) { | 243 | if (reference.file) { |
| @@ -223,10 +246,10 @@ void RealVfsFilesystem::EvictSingleReference() { | |||
| 223 | } | 246 | } |
| 224 | 247 | ||
| 225 | // Reinsert into closed list. | 248 | // Reinsert into closed list. |
| 226 | this->InsertReferenceIntoList(reference); | 249 | this->InsertReferenceIntoListLocked(reference); |
| 227 | } | 250 | } |
| 228 | 251 | ||
| 229 | void RealVfsFilesystem::InsertReferenceIntoList(FileReference& reference) { | 252 | void RealVfsFilesystem::InsertReferenceIntoListLocked(FileReference& reference) { |
| 230 | if (reference.file) { | 253 | if (reference.file) { |
| 231 | open_references.push_front(reference); | 254 | open_references.push_front(reference); |
| 232 | } else { | 255 | } else { |
| @@ -234,7 +257,7 @@ void RealVfsFilesystem::InsertReferenceIntoList(FileReference& reference) { | |||
| 234 | } | 257 | } |
| 235 | } | 258 | } |
| 236 | 259 | ||
| 237 | void RealVfsFilesystem::RemoveReferenceFromList(FileReference& reference) { | 260 | void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference) { |
| 238 | if (reference.file) { | 261 | if (reference.file) { |
| 239 | open_references.erase(open_references.iterator_to(reference)); | 262 | open_references.erase(open_references.iterator_to(reference)); |
| 240 | } else { | 263 | } else { |
| @@ -243,10 +266,10 @@ void RealVfsFilesystem::RemoveReferenceFromList(FileReference& reference) { | |||
| 243 | } | 266 | } |
| 244 | 267 | ||
| 245 | RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, | 268 | RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, |
| 246 | const std::string& path_, Mode perms_) | 269 | const std::string& path_, Mode perms_, std::optional<u64> size_) |
| 247 | : base(base_), reference(std::move(reference_)), path(path_), | 270 | : base(base_), reference(std::move(reference_)), path(path_), |
| 248 | parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), | 271 | parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), |
| 249 | perms(perms_) {} | 272 | size(size_), perms(perms_) {} |
| 250 | 273 | ||
| 251 | RealVfsFile::~RealVfsFile() { | 274 | RealVfsFile::~RealVfsFile() { |
| 252 | base.DropReference(std::move(reference)); | 275 | base.DropReference(std::move(reference)); |
| @@ -257,12 +280,15 @@ std::string RealVfsFile::GetName() const { | |||
| 257 | } | 280 | } |
| 258 | 281 | ||
| 259 | std::size_t RealVfsFile::GetSize() const { | 282 | std::size_t RealVfsFile::GetSize() const { |
| 260 | base.RefreshReference(path, perms, *reference); | 283 | if (size) { |
| 261 | return reference->file ? reference->file->GetSize() : 0; | 284 | return *size; |
| 285 | } | ||
| 286 | return FS::GetSize(path); | ||
| 262 | } | 287 | } |
| 263 | 288 | ||
| 264 | bool RealVfsFile::Resize(std::size_t new_size) { | 289 | bool RealVfsFile::Resize(std::size_t new_size) { |
| 265 | base.RefreshReference(path, perms, *reference); | 290 | size.reset(); |
| 291 | auto lk = base.RefreshReference(path, perms, *reference); | ||
| 266 | return reference->file ? reference->file->SetSize(new_size) : false; | 292 | return reference->file ? reference->file->SetSize(new_size) : false; |
| 267 | } | 293 | } |
| 268 | 294 | ||
| @@ -279,7 +305,7 @@ bool RealVfsFile::IsReadable() const { | |||
| 279 | } | 305 | } |
| 280 | 306 | ||
| 281 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { | 307 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 282 | base.RefreshReference(path, perms, *reference); | 308 | auto lk = base.RefreshReference(path, perms, *reference); |
| 283 | if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { | 309 | if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { |
| 284 | return 0; | 310 | return 0; |
| 285 | } | 311 | } |
| @@ -287,7 +313,8 @@ std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) | |||
| 287 | } | 313 | } |
| 288 | 314 | ||
| 289 | std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { | 315 | std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { |
| 290 | base.RefreshReference(path, perms, *reference); | 316 | size.reset(); |
| 317 | auto lk = base.RefreshReference(path, perms, *reference); | ||
| 291 | if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { | 318 | if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { |
| 292 | return 0; | 319 | return 0; |
| 293 | } | 320 | } |
| @@ -309,10 +336,11 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>( | |||
| 309 | 336 | ||
| 310 | std::vector<VirtualFile> out; | 337 | std::vector<VirtualFile> out; |
| 311 | 338 | ||
| 312 | const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { | 339 | const FS::DirEntryCallable callback = [this, |
| 313 | const auto full_path_string = FS::PathToUTF8String(full_path); | 340 | &out](const std::filesystem::directory_entry& entry) { |
| 341 | const auto full_path_string = FS::PathToUTF8String(entry.path()); | ||
| 314 | 342 | ||
| 315 | out.emplace_back(base.OpenFile(full_path_string, perms)); | 343 | out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), perms)); |
| 316 | 344 | ||
| 317 | return true; | 345 | return true; |
| 318 | }; | 346 | }; |
| @@ -330,8 +358,9 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi | |||
| 330 | 358 | ||
| 331 | std::vector<VirtualDir> out; | 359 | std::vector<VirtualDir> out; |
| 332 | 360 | ||
| 333 | const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { | 361 | const FS::DirEntryCallable callback = [this, |
| 334 | const auto full_path_string = FS::PathToUTF8String(full_path); | 362 | &out](const std::filesystem::directory_entry& entry) { |
| 363 | const auto full_path_string = FS::PathToUTF8String(entry.path()); | ||
| 335 | 364 | ||
| 336 | out.emplace_back(base.OpenDirectory(full_path_string, perms)); | 365 | out.emplace_back(base.OpenDirectory(full_path_string, perms)); |
| 337 | 366 | ||
| @@ -483,12 +512,10 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries() | |||
| 483 | 512 | ||
| 484 | std::map<std::string, VfsEntryType, std::less<>> out; | 513 | std::map<std::string, VfsEntryType, std::less<>> out; |
| 485 | 514 | ||
| 486 | const FS::DirEntryCallable callback = [&out](const std::filesystem::path& full_path) { | 515 | const FS::DirEntryCallable callback = [&out](const std::filesystem::directory_entry& entry) { |
| 487 | const auto filename = FS::PathToUTF8String(full_path.filename()); | 516 | const auto filename = FS::PathToUTF8String(entry.path().filename()); |
| 488 | |||
| 489 | out.insert_or_assign(filename, | 517 | out.insert_or_assign(filename, |
| 490 | FS::IsDir(full_path) ? VfsEntryType::Directory : VfsEntryType::File); | 518 | entry.is_directory() ? VfsEntryType::Directory : VfsEntryType::File); |
| 491 | |||
| 492 | return true; | 519 | return true; |
| 493 | }; | 520 | }; |
| 494 | 521 | ||
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index d8c900e33..26ea7df62 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <map> | 6 | #include <map> |
| 7 | #include <mutex> | ||
| 8 | #include <optional> | ||
| 7 | #include <string_view> | 9 | #include <string_view> |
| 8 | #include "common/intrusive_list.h" | 10 | #include "common/intrusive_list.h" |
| 9 | #include "core/file_sys/mode.h" | 11 | #include "core/file_sys/mode.h" |
| @@ -20,6 +22,8 @@ struct FileReference : public Common::IntrusiveListBaseNode<FileReference> { | |||
| 20 | }; | 22 | }; |
| 21 | 23 | ||
| 22 | class RealVfsFile; | 24 | class RealVfsFile; |
| 25 | class RealVfsDirectory; | ||
| 26 | |||
| 23 | class RealVfsFilesystem : public VfsFilesystem { | 27 | class RealVfsFilesystem : public VfsFilesystem { |
| 24 | public: | 28 | public: |
| 25 | RealVfsFilesystem(); | 29 | RealVfsFilesystem(); |
| @@ -45,17 +49,24 @@ private: | |||
| 45 | std::map<std::string, std::weak_ptr<VfsFile>, std::less<>> cache; | 49 | std::map<std::string, std::weak_ptr<VfsFile>, std::less<>> cache; |
| 46 | ReferenceListType open_references; | 50 | ReferenceListType open_references; |
| 47 | ReferenceListType closed_references; | 51 | ReferenceListType closed_references; |
| 52 | std::mutex list_lock; | ||
| 48 | size_t num_open_files{}; | 53 | size_t num_open_files{}; |
| 49 | 54 | ||
| 50 | private: | 55 | private: |
| 51 | friend class RealVfsFile; | 56 | friend class RealVfsFile; |
| 52 | void RefreshReference(const std::string& path, Mode perms, FileReference& reference); | 57 | std::unique_lock<std::mutex> RefreshReference(const std::string& path, Mode perms, |
| 58 | FileReference& reference); | ||
| 53 | void DropReference(std::unique_ptr<FileReference>&& reference); | 59 | void DropReference(std::unique_ptr<FileReference>&& reference); |
| 54 | void EvictSingleReference(); | ||
| 55 | 60 | ||
| 56 | private: | 61 | private: |
| 57 | void InsertReferenceIntoList(FileReference& reference); | 62 | friend class RealVfsDirectory; |
| 58 | void RemoveReferenceFromList(FileReference& reference); | 63 | VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size, |
| 64 | Mode perms = Mode::Read); | ||
| 65 | |||
| 66 | private: | ||
| 67 | void EvictSingleReferenceLocked(); | ||
| 68 | void InsertReferenceIntoListLocked(FileReference& reference); | ||
| 69 | void RemoveReferenceFromListLocked(FileReference& reference); | ||
| 59 | }; | 70 | }; |
| 60 | 71 | ||
| 61 | // An implementation of VfsFile that represents a file on the user's computer. | 72 | // An implementation of VfsFile that represents a file on the user's computer. |
| @@ -78,13 +89,14 @@ public: | |||
| 78 | 89 | ||
| 79 | private: | 90 | private: |
| 80 | RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference, | 91 | RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference, |
| 81 | const std::string& path, Mode perms = Mode::Read); | 92 | const std::string& path, Mode perms = Mode::Read, std::optional<u64> size = {}); |
| 82 | 93 | ||
| 83 | RealVfsFilesystem& base; | 94 | RealVfsFilesystem& base; |
| 84 | std::unique_ptr<FileReference> reference; | 95 | std::unique_ptr<FileReference> reference; |
| 85 | std::string path; | 96 | std::string path; |
| 86 | std::string parent_path; | 97 | std::string parent_path; |
| 87 | std::vector<std::string> path_components; | 98 | std::vector<std::string> path_components; |
| 99 | std::optional<u64> size; | ||
| 88 | Mode perms; | 100 | Mode perms; |
| 89 | }; | 101 | }; |
| 90 | 102 | ||