summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Morph2021-05-25 19:32:56 -0400
committerGravatar GitHub2021-05-25 19:32:56 -0400
commit065867e2c24e9856c360fc2d6b9a86c92aedc43e (patch)
tree7964e85ef4f01a3c2b8f44e850f37b384405b930 /src/core
parentMerge pull request #6349 from german77/suppress_config_warning (diff)
downloadyuzu-065867e2c24e9856c360fc2d6b9a86c92aedc43e.tar.gz
yuzu-065867e2c24e9856c360fc2d6b9a86c92aedc43e.tar.xz
yuzu-065867e2c24e9856c360fc2d6b9a86c92aedc43e.zip
common: fs: Rework the Common Filesystem interface to make use of std::filesystem (#6270)
* common: fs: fs_types: Create filesystem types Contains various filesystem types used by the Common::FS library * common: fs: fs_util: Add std::string to std::u8string conversion utility * common: fs: path_util: Add utlity functions for paths Contains various utility functions for getting or manipulating filesystem paths used by the Common::FS library * common: fs: file: Rewrite the IOFile implementation * common: fs: Reimplement Common::FS library using std::filesystem * common: fs: fs_paths: Add fs_paths to replace common_paths * common: fs: path_util: Add the rest of the path functions * common: Remove the previous Common::FS implementation * general: Remove unused fs includes * string_util: Remove unused function and include * nvidia_flags: Migrate to the new Common::FS library * settings: Migrate to the new Common::FS library * logging: backend: Migrate to the new Common::FS library * core: Migrate to the new Common::FS library * perf_stats: Migrate to the new Common::FS library * reporter: Migrate to the new Common::FS library * telemetry_session: Migrate to the new Common::FS library * key_manager: Migrate to the new Common::FS library * bis_factory: Migrate to the new Common::FS library * registered_cache: Migrate to the new Common::FS library * xts_archive: Migrate to the new Common::FS library * service: acc: Migrate to the new Common::FS library * applets/profile: Migrate to the new Common::FS library * applets/web: Migrate to the new Common::FS library * service: filesystem: Migrate to the new Common::FS library * loader: Migrate to the new Common::FS library * gl_shader_disk_cache: Migrate to the new Common::FS library * nsight_aftermath_tracker: Migrate to the new Common::FS library * vulkan_library: Migrate to the new Common::FS library * configure_debug: Migrate to the new Common::FS library * game_list_worker: Migrate to the new Common::FS library * config: Migrate to the new Common::FS library * configure_filesystem: Migrate to the new Common::FS library * configure_per_game_addons: Migrate to the new Common::FS library * configure_profile_manager: Migrate to the new Common::FS library * configure_ui: Migrate to the new Common::FS library * input_profiles: Migrate to the new Common::FS library * yuzu_cmd: config: Migrate to the new Common::FS library * yuzu_cmd: Migrate to the new Common::FS library * vfs_real: Migrate to the new Common::FS library * vfs: Migrate to the new Common::FS library * vfs_libzip: Migrate to the new Common::FS library * service: bcat: Migrate to the new Common::FS library * yuzu: main: Migrate to the new Common::FS library * vfs_real: Delete the contents of an existing file in CreateFile Current usages of CreateFile expect to delete the contents of an existing file, retain this behavior for now. * input_profiles: Don't iterate the input profile dir if it does not exist Silences an error produced in the log if the directory does not exist. * game_list_worker: Skip parsing file if the returned VfsFile is nullptr Prevents crashes in GetLoader when the virtual file is nullptr * common: fs: Validate paths for path length * service: filesystem: Open the mod load directory as read only
Diffstat (limited to 'src/core')
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/crypto/key_manager.cpp139
-rw-r--r--src/core/crypto/key_manager.h6
-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
-rw-r--r--src/core/hle/service/acc/acc.cpp28
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp33
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp47
-rw-r--r--src/core/hle/service/am/applets/web_browser.h5
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp68
-rw-r--r--src/core/hle/service/fatal/fatal.cpp1
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp21
-rw-r--r--src/core/hle/service/mii/manager.cpp1
-rw-r--r--src/core/hle/service/ns/pl_u.cpp2
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp1
-rw-r--r--src/core/loader/elf.cpp1
-rw-r--r--src/core/loader/loader.cpp2
-rw-r--r--src/core/loader/nca.cpp1
-rw-r--r--src/core/loader/nro.cpp1
-rw-r--r--src/core/loader/nso.cpp1
-rw-r--r--src/core/perf_stats.cpp19
-rw-r--r--src/core/reporter.cpp23
-rw-r--r--src/core/telemetry_session.cpp47
31 files changed, 387 insertions, 340 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 826a00ad6..c5004b7b4 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -6,7 +6,7 @@
6#include <memory> 6#include <memory>
7#include <utility> 7#include <utility>
8 8
9#include "common/file_util.h" 9#include "common/fs/fs.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/microprofile.h" 11#include "common/microprofile.h"
12#include "common/settings.h" 12#include "common/settings.h"
@@ -121,7 +121,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
121 dir->GetName()); 121 dir->GetName());
122 } 122 }
123 123
124 if (Common::FS::IsDirectory(path)) { 124 if (Common::FS::IsDir(path)) {
125 return vfs->OpenFile(path + "/main", FileSys::Mode::Read); 125 return vfs->OpenFile(path + "/main", FileSys::Mode::Read);
126 } 126 }
127 127
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index a4b739c63..fb451a423 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -18,8 +18,9 @@
18#include <mbedtls/cmac.h> 18#include <mbedtls/cmac.h>
19#include <mbedtls/sha256.h> 19#include <mbedtls/sha256.h>
20#include "common/common_funcs.h" 20#include "common/common_funcs.h"
21#include "common/common_paths.h" 21#include "common/fs/file.h"
22#include "common/file_util.h" 22#include "common/fs/fs.h"
23#include "common/fs/path_util.h"
23#include "common/hex_util.h" 24#include "common/hex_util.h"
24#include "common/logging/log.h" 25#include "common/logging/log.h"
25#include "common/settings.h" 26#include "common/settings.h"
@@ -325,46 +326,55 @@ Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source)
325} 326}
326 327
327std::optional<Key128> DeriveSDSeed() { 328std::optional<Key128> DeriveSDSeed() {
328 const Common::FS::IOFile save_43(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + 329 const auto system_save_43_path =
329 "/system/save/8000000000000043", 330 Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000043";
330 "rb+"); 331 const Common::FS::IOFile save_43{system_save_43_path, Common::FS::FileAccessMode::Read,
332 Common::FS::FileType::BinaryFile};
333
331 if (!save_43.IsOpen()) { 334 if (!save_43.IsOpen()) {
332 return std::nullopt; 335 return std::nullopt;
333 } 336 }
334 337
335 const Common::FS::IOFile sd_private(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir) + 338 const auto sd_private_path =
336 "/Nintendo/Contents/private", 339 Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "Nintendo/Contents/private";
337 "rb+"); 340
341 const Common::FS::IOFile sd_private{sd_private_path, Common::FS::FileAccessMode::Read,
342 Common::FS::FileType::BinaryFile};
343
338 if (!sd_private.IsOpen()) { 344 if (!sd_private.IsOpen()) {
339 return std::nullopt; 345 return std::nullopt;
340 } 346 }
341 347
342 std::array<u8, 0x10> private_seed{}; 348 std::array<u8, 0x10> private_seed{};
343 if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) { 349 if (sd_private.Read(private_seed) != private_seed.size()) {
344 return std::nullopt; 350 return std::nullopt;
345 } 351 }
346 352
347 std::array<u8, 0x10> buffer{}; 353 std::array<u8, 0x10> buffer{};
348 std::size_t offset = 0; 354 s64 offset = 0;
349 for (; offset + 0x10 < save_43.GetSize(); ++offset) { 355 for (; offset + 0x10 < static_cast<s64>(save_43.GetSize()); ++offset) {
350 if (!save_43.Seek(offset, SEEK_SET)) { 356 if (!save_43.Seek(offset)) {
357 return std::nullopt;
358 }
359
360 if (save_43.Read(buffer) != buffer.size()) {
351 return std::nullopt; 361 return std::nullopt;
352 } 362 }
353 363
354 save_43.ReadBytes(buffer.data(), buffer.size());
355 if (buffer == private_seed) { 364 if (buffer == private_seed) {
356 break; 365 break;
357 } 366 }
358 } 367 }
359 368
360 if (!save_43.Seek(offset + 0x10, SEEK_SET)) { 369 if (!save_43.Seek(offset + 0x10)) {
361 return std::nullopt; 370 return std::nullopt;
362 } 371 }
363 372
364 Key128 seed{}; 373 Key128 seed{};
365 if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) { 374 if (save_43.Read(seed) != seed.size()) {
366 return std::nullopt; 375 return std::nullopt;
367 } 376 }
377
368 return seed; 378 return seed;
369} 379}
370 380
@@ -435,7 +445,7 @@ std::vector<Ticket> GetTicketblob(const Common::FS::IOFile& ticket_save) {
435 } 445 }
436 446
437 std::vector<u8> buffer(ticket_save.GetSize()); 447 std::vector<u8> buffer(ticket_save.GetSize());
438 if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) { 448 if (ticket_save.Read(buffer) != buffer.size()) {
439 return {}; 449 return {};
440 } 450 }
441 451
@@ -566,27 +576,26 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
566 576
567KeyManager::KeyManager() { 577KeyManager::KeyManager() {
568 // Initialize keys 578 // Initialize keys
569 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath(); 579 const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
570 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir);
571 580
572 if (!Common::FS::Exists(yuzu_keys_dir)) { 581 if (!Common::FS::CreateDir(yuzu_keys_dir)) {
573 Common::FS::CreateDir(yuzu_keys_dir); 582 LOG_ERROR(Core, "Failed to create the keys directory.");
574 } 583 }
575 584
576 if (Settings::values.use_dev_keys) { 585 if (Settings::values.use_dev_keys) {
577 dev_mode = true; 586 dev_mode = true;
578 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false); 587 LoadFromFile(yuzu_keys_dir / "dev.keys", false);
579 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "dev.keys_autogenerated", false); 588 LoadFromFile(yuzu_keys_dir / "dev.keys_autogenerated", false);
580 } else { 589 } else {
581 dev_mode = false; 590 dev_mode = false;
582 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "prod.keys", false); 591 LoadFromFile(yuzu_keys_dir / "prod.keys", false);
583 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "prod.keys_autogenerated", false); 592 LoadFromFile(yuzu_keys_dir / "prod.keys_autogenerated", false);
584 } 593 }
585 594
586 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "title.keys", true); 595 LoadFromFile(yuzu_keys_dir / "title.keys", true);
587 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "title.keys_autogenerated", true); 596 LoadFromFile(yuzu_keys_dir / "title.keys_autogenerated", true);
588 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "console.keys", false); 597 LoadFromFile(yuzu_keys_dir / "console.keys", false);
589 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "console.keys_autogenerated", false); 598 LoadFromFile(yuzu_keys_dir / "console.keys_autogenerated", false);
590} 599}
591 600
592static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { 601static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) {
@@ -597,9 +606,14 @@ static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_
597 [](u8 c) { return std::isxdigit(c); }); 606 [](u8 c) { return std::isxdigit(c); });
598} 607}
599 608
600void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { 609void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys) {
610 if (!Common::FS::Exists(file_path)) {
611 return;
612 }
613
601 std::ifstream file; 614 std::ifstream file;
602 Common::FS::OpenFStream(file, filename, std::ios_base::in); 615 Common::FS::OpenFileStream(file, file_path, std::ios_base::in);
616
603 if (!file.is_open()) { 617 if (!file.is_open()) {
604 return; 618 return;
605 } 619 }
@@ -694,15 +708,6 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
694 } 708 }
695} 709}
696 710
697void KeyManager::AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2,
698 const std::string& filename, bool title) {
699 if (Common::FS::Exists(dir1 + DIR_SEP + filename)) {
700 LoadFromFile(dir1 + DIR_SEP + filename, title);
701 } else if (Common::FS::Exists(dir2 + DIR_SEP + filename)) {
702 LoadFromFile(dir2 + DIR_SEP + filename, title);
703 }
704}
705
706bool KeyManager::BaseDeriveNecessary() const { 711bool KeyManager::BaseDeriveNecessary() const {
707 const auto check_key_existence = [this](auto key_type, u64 index1 = 0, u64 index2 = 0) { 712 const auto check_key_existence = [this](auto key_type, u64 index1 = 0, u64 index2 = 0) {
708 return !HasKey(key_type, index1, index2); 713 return !HasKey(key_type, index1, index2);
@@ -766,30 +771,35 @@ Key256 KeyManager::GetBISKey(u8 partition_id) const {
766template <size_t Size> 771template <size_t Size>
767void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, 772void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
768 const std::array<u8, Size>& key) { 773 const std::array<u8, Size>& key) {
769 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); 774 const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
775
770 std::string filename = "title.keys_autogenerated"; 776 std::string filename = "title.keys_autogenerated";
777
771 if (category == KeyCategory::Standard) { 778 if (category == KeyCategory::Standard) {
772 filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated"; 779 filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated";
773 } else if (category == KeyCategory::Console) { 780 } else if (category == KeyCategory::Console) {
774 filename = "console.keys_autogenerated"; 781 filename = "console.keys_autogenerated";
775 } 782 }
776 783
777 const auto path = yuzu_keys_dir + DIR_SEP + filename; 784 const auto path = yuzu_keys_dir / filename;
778 const auto add_info_text = !Common::FS::Exists(path); 785 const auto add_info_text = !Common::FS::Exists(path);
779 Common::FS::CreateFullPath(path); 786
780 Common::FS::IOFile file{path, "a"}; 787 Common::FS::IOFile file{path, Common::FS::FileAccessMode::Append,
788 Common::FS::FileType::TextFile};
789
781 if (!file.IsOpen()) { 790 if (!file.IsOpen()) {
782 return; 791 return;
783 } 792 }
793
784 if (add_info_text) { 794 if (add_info_text) {
785 file.WriteString( 795 void(file.WriteString(
786 "# This file is autogenerated by Yuzu\n" 796 "# This file is autogenerated by Yuzu\n"
787 "# It serves to store keys that were automatically generated from the normal keys\n" 797 "# It serves to store keys that were automatically generated from the normal keys\n"
788 "# If you are experiencing issues involving keys, it may help to delete this file\n"); 798 "# If you are experiencing issues involving keys, it may help to delete this file\n"));
789 } 799 }
790 800
791 file.WriteString(fmt::format("\n{} = {}", keyname, Common::HexToString(key))); 801 void(file.WriteString(fmt::format("\n{} = {}", keyname, Common::HexToString(key))));
792 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, filename, category == KeyCategory::Title); 802 LoadFromFile(path, category == KeyCategory::Title);
793} 803}
794 804
795void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) { 805void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
@@ -861,20 +871,17 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) {
861} 871}
862 872
863bool KeyManager::KeyFileExists(bool title) { 873bool KeyManager::KeyFileExists(bool title) {
864 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath(); 874 const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
865 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); 875
866 if (title) { 876 if (title) {
867 return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "title.keys") || 877 return Common::FS::Exists(yuzu_keys_dir / "title.keys");
868 Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "title.keys");
869 } 878 }
870 879
871 if (Settings::values.use_dev_keys) { 880 if (Settings::values.use_dev_keys) {
872 return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "dev.keys") || 881 return Common::FS::Exists(yuzu_keys_dir / "dev.keys");
873 Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "dev.keys");
874 } 882 }
875 883
876 return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "prod.keys") || 884 return Common::FS::Exists(yuzu_keys_dir / "prod.keys");
877 Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "prod.keys");
878} 885}
879 886
880void KeyManager::DeriveSDSeedLazy() { 887void KeyManager::DeriveSDSeedLazy() {
@@ -1115,15 +1122,21 @@ void KeyManager::PopulateTickets() {
1115 return; 1122 return;
1116 } 1123 }
1117 1124
1118 const Common::FS::IOFile save1(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + 1125 const auto system_save_e1_path =
1119 "/system/save/80000000000000e1", 1126 Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/80000000000000e1";
1120 "rb+"); 1127
1121 const Common::FS::IOFile save2(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + 1128 const Common::FS::IOFile save_e1{system_save_e1_path, Common::FS::FileAccessMode::Read,
1122 "/system/save/80000000000000e2", 1129 Common::FS::FileType::BinaryFile};
1123 "rb+"); 1130
1131 const auto system_save_e2_path =
1132 Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/80000000000000e2";
1133
1134 const Common::FS::IOFile save_e2{system_save_e2_path, Common::FS::FileAccessMode::Read,
1135 Common::FS::FileType::BinaryFile};
1136
1137 const auto blob2 = GetTicketblob(save_e2);
1138 auto res = GetTicketblob(save_e1);
1124 1139
1125 const auto blob2 = GetTicketblob(save2);
1126 auto res = GetTicketblob(save1);
1127 const auto idx = res.size(); 1140 const auto idx = res.size();
1128 res.insert(res.end(), blob2.begin(), blob2.end()); 1141 res.insert(res.end(), blob2.begin(), blob2.end());
1129 1142
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h
index 0a7220286..e771625e1 100644
--- a/src/core/crypto/key_manager.h
+++ b/src/core/crypto/key_manager.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <filesystem>
8#include <map> 9#include <map>
9#include <optional> 10#include <optional>
10#include <string> 11#include <string>
@@ -283,9 +284,8 @@ private:
283 std::array<u8, 576> eticket_extended_kek{}; 284 std::array<u8, 576> eticket_extended_kek{};
284 285
285 bool dev_mode; 286 bool dev_mode;
286 void LoadFromFile(const std::string& filename, bool is_title_keys); 287 void LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys);
287 void AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2, 288
288 const std::string& filename, bool title);
289 template <size_t Size> 289 template <size_t Size>
290 void WriteKeyToFile(KeyCategory category, std::string_view keyname, 290 void WriteKeyToFile(KeyCategory category, std::string_view keyname,
291 const std::array<u8, Size>& key); 291 const std::array<u8, Size>& key);
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"
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 49c09a570..39cd1efc1 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -4,9 +4,9 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <array> 6#include <array>
7#include "common/common_paths.h"
8#include "common/common_types.h" 7#include "common/common_types.h"
9#include "common/file_util.h" 8#include "common/fs/file.h"
9#include "common/fs/path_util.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/string_util.h" 11#include "common/string_util.h"
12#include "common/swap.h" 12#include "common/swap.h"
@@ -41,9 +41,9 @@ constexpr ResultCode ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100};
41// Thumbnails are hard coded to be at least this size 41// Thumbnails are hard coded to be at least this size
42constexpr std::size_t THUMBNAIL_SIZE = 0x24000; 42constexpr std::size_t THUMBNAIL_SIZE = 0x24000;
43 43
44static std::string GetImagePath(Common::UUID uuid) { 44static std::filesystem::path GetImagePath(Common::UUID uuid) {
45 return Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + 45 return Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) /
46 "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; 46 fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormatSwitch());
47} 47}
48 48
49static constexpr u32 SanitizeJPEGSize(std::size_t size) { 49static constexpr u32 SanitizeJPEGSize(std::size_t size) {
@@ -328,7 +328,8 @@ protected:
328 IPC::ResponseBuilder rb{ctx, 3}; 328 IPC::ResponseBuilder rb{ctx, 3};
329 rb.Push(RESULT_SUCCESS); 329 rb.Push(RESULT_SUCCESS);
330 330
331 const Common::FS::IOFile image(GetImagePath(user_id), "rb"); 331 const Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Read,
332 Common::FS::FileType::BinaryFile);
332 if (!image.IsOpen()) { 333 if (!image.IsOpen()) {
333 LOG_WARNING(Service_ACC, 334 LOG_WARNING(Service_ACC,
334 "Failed to load user provided image! Falling back to built-in backup..."); 335 "Failed to load user provided image! Falling back to built-in backup...");
@@ -339,7 +340,10 @@ protected:
339 340
340 const u32 size = SanitizeJPEGSize(image.GetSize()); 341 const u32 size = SanitizeJPEGSize(image.GetSize());
341 std::vector<u8> buffer(size); 342 std::vector<u8> buffer(size);
342 image.ReadBytes(buffer.data(), buffer.size()); 343
344 if (image.Read(buffer) != buffer.size()) {
345 LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
346 }
343 347
344 ctx.WriteBuffer(buffer); 348 ctx.WriteBuffer(buffer);
345 rb.Push<u32>(size); 349 rb.Push<u32>(size);
@@ -350,7 +354,8 @@ protected:
350 IPC::ResponseBuilder rb{ctx, 3}; 354 IPC::ResponseBuilder rb{ctx, 3};
351 rb.Push(RESULT_SUCCESS); 355 rb.Push(RESULT_SUCCESS);
352 356
353 const Common::FS::IOFile image(GetImagePath(user_id), "rb"); 357 const Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Read,
358 Common::FS::FileType::BinaryFile);
354 359
355 if (!image.IsOpen()) { 360 if (!image.IsOpen()) {
356 LOG_WARNING(Service_ACC, 361 LOG_WARNING(Service_ACC,
@@ -415,10 +420,11 @@ protected:
415 ProfileData data; 420 ProfileData data;
416 std::memcpy(&data, user_data.data(), sizeof(ProfileData)); 421 std::memcpy(&data, user_data.data(), sizeof(ProfileData));
417 422
418 Common::FS::IOFile image(GetImagePath(user_id), "wb"); 423 Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Write,
424 Common::FS::FileType::BinaryFile);
419 425
420 if (!image.IsOpen() || !image.Resize(image_data.size()) || 426 if (!image.IsOpen() || !image.SetSize(image_data.size()) ||
421 image.WriteBytes(image_data.data(), image_data.size()) != image_data.size() || 427 image.Write(image_data) != image_data.size() ||
422 !profile_manager.SetProfileBaseAndData(user_id, base, data)) { 428 !profile_manager.SetProfileBaseAndData(user_id, base, data)) {
423 LOG_ERROR(Service_ACC, "Failed to update profile data, base, and image!"); 429 LOG_ERROR(Service_ACC, "Failed to update profile data, base, and image!");
424 IPC::ResponseBuilder rb{ctx, 2}; 430 IPC::ResponseBuilder rb{ctx, 2};
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index de83d82a4..77510489c 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -7,7 +7,9 @@
7 7
8#include <fmt/format.h> 8#include <fmt/format.h>
9 9
10#include "common/file_util.h" 10#include "common/fs/file.h"
11#include "common/fs/fs.h"
12#include "common/fs/path_util.h"
11#include "common/settings.h" 13#include "common/settings.h"
12#include "core/hle/service/acc/profile_manager.h" 14#include "core/hle/service/acc/profile_manager.h"
13 15
@@ -36,7 +38,7 @@ constexpr ResultCode ERROR_TOO_MANY_USERS(ErrorModule::Account, u32(-1));
36constexpr ResultCode ERROR_USER_ALREADY_EXISTS(ErrorModule::Account, u32(-2)); 38constexpr ResultCode ERROR_USER_ALREADY_EXISTS(ErrorModule::Account, u32(-2));
37constexpr ResultCode ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20); 39constexpr ResultCode ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20);
38 40
39constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "/system/save/8000000000000010/su/avators/"; 41constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "system/save/8000000000000010/su/avators";
40 42
41ProfileManager::ProfileManager() { 43ProfileManager::ProfileManager() {
42 ParseUserSaveFile(); 44 ParseUserSaveFile();
@@ -325,8 +327,9 @@ bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase&
325} 327}
326 328
327void ProfileManager::ParseUserSaveFile() { 329void ProfileManager::ParseUserSaveFile() {
328 const FS::IOFile save( 330 const auto save_path(FS::GetYuzuPath(FS::YuzuPath::NANDDir) / ACC_SAVE_AVATORS_BASE_PATH /
329 FS::GetUserPath(FS::UserPath::NANDDir) + ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat", "rb"); 331 "profiles.dat");
332 const FS::IOFile save(save_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile);
330 333
331 if (!save.IsOpen()) { 334 if (!save.IsOpen()) {
332 LOG_WARNING(Service_ACC, "Failed to load profile data from save data... Generating new " 335 LOG_WARNING(Service_ACC, "Failed to load profile data from save data... Generating new "
@@ -335,7 +338,7 @@ void ProfileManager::ParseUserSaveFile() {
335 } 338 }
336 339
337 ProfileDataRaw data; 340 ProfileDataRaw data;
338 if (save.ReadBytes(&data, sizeof(ProfileDataRaw)) != sizeof(ProfileDataRaw)) { 341 if (!save.ReadObject(data)) {
339 LOG_WARNING(Service_ACC, "profiles.dat is smaller than expected... Generating new user " 342 LOG_WARNING(Service_ACC, "profiles.dat is smaller than expected... Generating new user "
340 "'yuzu' with random UUID."); 343 "'yuzu' with random UUID.");
341 return; 344 return;
@@ -372,31 +375,27 @@ void ProfileManager::WriteUserSaveFile() {
372 }; 375 };
373 } 376 }
374 377
375 const auto raw_path = FS::GetUserPath(FS::UserPath::NANDDir) + "/system/save/8000000000000010"; 378 const auto raw_path(FS::GetYuzuPath(FS::YuzuPath::NANDDir) / "system/save/8000000000000010");
376 if (FS::Exists(raw_path) && !FS::IsDirectory(raw_path)) { 379 if (FS::IsFile(raw_path) && !FS::RemoveFile(raw_path)) {
377 FS::Delete(raw_path); 380 return;
378 } 381 }
379 382
380 const auto path = 383 const auto save_path(FS::GetYuzuPath(FS::YuzuPath::NANDDir) / ACC_SAVE_AVATORS_BASE_PATH /
381 FS::GetUserPath(FS::UserPath::NANDDir) + ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat"; 384 "profiles.dat");
382 385
383 if (!FS::CreateFullPath(path)) { 386 if (!FS::CreateParentDirs(save_path)) {
384 LOG_WARNING(Service_ACC, "Failed to create full path of profiles.dat. Create the directory " 387 LOG_WARNING(Service_ACC, "Failed to create full path of profiles.dat. Create the directory "
385 "nand/system/save/8000000000000010/su/avators to mitigate this " 388 "nand/system/save/8000000000000010/su/avators to mitigate this "
386 "issue."); 389 "issue.");
387 return; 390 return;
388 } 391 }
389 392
390 FS::IOFile save(path, "wb"); 393 FS::IOFile save(save_path, FS::FileAccessMode::Write, FS::FileType::BinaryFile);
391 394
392 if (!save.IsOpen()) { 395 if (!save.IsOpen() || !save.SetSize(sizeof(ProfileDataRaw)) || !save.WriteObject(raw)) {
393 LOG_WARNING(Service_ACC, "Failed to write save data to file... No changes to user data " 396 LOG_WARNING(Service_ACC, "Failed to write save data to file... No changes to user data "
394 "made in current session will be saved."); 397 "made in current session will be saved.");
395 return;
396 } 398 }
397
398 save.Resize(sizeof(ProfileDataRaw));
399 save.WriteBytes(&raw, sizeof(ProfileDataRaw));
400} 399}
401 400
402}; // namespace Service::Account 401}; // namespace Service::Account
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index e5f4a4485..3b28e829b 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -3,8 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_paths.h" 6#include "common/fs/file.h"
7#include "common/file_util.h" 7#include "common/fs/fs.h"
8#include "common/fs/path_util.h"
8#include "common/logging/log.h" 9#include "common/logging/log.h"
9#include "common/string_util.h" 10#include "common/string_util.h"
10#include "core/core.h" 11#include "core/core.h"
@@ -135,14 +136,10 @@ void ExtractSharedFonts(Core::System& system) {
135 "FontNintendoExtended2.ttf", 136 "FontNintendoExtended2.ttf",
136 }; 137 };
137 138
138 for (std::size_t i = 0; i < NS::SHARED_FONTS.size(); ++i) { 139 const auto fonts_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "fonts";
139 const auto fonts_dir = Common::FS::SanitizePath(
140 fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)),
141 Common::FS::DirectorySeparator::PlatformDefault);
142 140
143 const auto font_file_path = 141 for (std::size_t i = 0; i < NS::SHARED_FONTS.size(); ++i) {
144 Common::FS::SanitizePath(fmt::format("{}/{}", fonts_dir, DECRYPTED_SHARED_FONTS[i]), 142 const auto font_file_path = fonts_dir / DECRYPTED_SHARED_FONTS[i];
145 Common::FS::DirectorySeparator::PlatformDefault);
146 143
147 if (Common::FS::Exists(font_file_path)) { 144 if (Common::FS::Exists(font_file_path)) {
148 continue; 145 continue;
@@ -197,8 +194,8 @@ void ExtractSharedFonts(Core::System& system) {
197 FileSys::VirtualFile decrypted_font = std::make_shared<FileSys::VectorVfsFile>( 194 FileSys::VirtualFile decrypted_font = std::make_shared<FileSys::VectorVfsFile>(
198 std::move(decrypted_data), DECRYPTED_SHARED_FONTS[i]); 195 std::move(decrypted_data), DECRYPTED_SHARED_FONTS[i]);
199 196
200 const auto temp_dir = 197 const auto temp_dir = system.GetFilesystem()->CreateDirectory(
201 system.GetFilesystem()->CreateDirectory(fonts_dir, FileSys::Mode::ReadWrite); 198 Common::FS::PathToUTF8String(fonts_dir), FileSys::Mode::ReadWrite);
202 199
203 const auto out_file = temp_dir->CreateFile(DECRYPTED_SHARED_FONTS[i]); 200 const auto out_file = temp_dir->CreateFile(DECRYPTED_SHARED_FONTS[i]);
204 201
@@ -312,13 +309,14 @@ void WebBrowser::Execute() {
312} 309}
313 310
314void WebBrowser::ExtractOfflineRomFS() { 311void WebBrowser::ExtractOfflineRomFS() {
315 LOG_DEBUG(Service_AM, "Extracting RomFS to {}", offline_cache_dir); 312 LOG_DEBUG(Service_AM, "Extracting RomFS to {}",
313 Common::FS::PathToUTF8String(offline_cache_dir));
316 314
317 const auto extracted_romfs_dir = 315 const auto extracted_romfs_dir =
318 FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard); 316 FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard);
319 317
320 const auto temp_dir = 318 const auto temp_dir = system.GetFilesystem()->CreateDirectory(
321 system.GetFilesystem()->CreateDirectory(offline_cache_dir, FileSys::Mode::ReadWrite); 319 Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite);
322 320
323 FileSys::VfsRawCopyD(extracted_romfs_dir, temp_dir); 321 FileSys::VfsRawCopyD(extracted_romfs_dir, temp_dir);
324} 322}
@@ -397,15 +395,12 @@ void WebBrowser::InitializeOffline() {
397 "system_data", 395 "system_data",
398 }; 396 };
399 397
400 offline_cache_dir = Common::FS::SanitizePath( 398 offline_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) /
401 fmt::format("{}/offline_web_applet_{}/{:016X}", 399 fmt::format("offline_web_applet_{}/{:016X}",
402 Common::FS::GetUserPath(Common::FS::UserPath::CacheDir), 400 RESOURCE_TYPES[static_cast<u32>(document_kind) - 1], title_id);
403 RESOURCE_TYPES[static_cast<u32>(document_kind) - 1], title_id),
404 Common::FS::DirectorySeparator::PlatformDefault);
405 401
406 offline_document = Common::FS::SanitizePath( 402 offline_document = Common::FS::ConcatPathSafe(
407 fmt::format("{}/{}/{}", offline_cache_dir, additional_paths, document_path), 403 offline_cache_dir, fmt::format("{}/{}", additional_paths, document_path));
408 Common::FS::DirectorySeparator::PlatformDefault);
409} 404}
410 405
411void WebBrowser::InitializeShare() {} 406void WebBrowser::InitializeShare() {}
@@ -429,8 +424,7 @@ void WebBrowser::ExecuteLogin() {
429} 424}
430 425
431void WebBrowser::ExecuteOffline() { 426void WebBrowser::ExecuteOffline() {
432 const auto main_url = Common::FS::SanitizePath(GetMainURL(offline_document), 427 const auto main_url = GetMainURL(Common::FS::PathToUTF8String(offline_document));
433 Common::FS::DirectorySeparator::PlatformDefault);
434 428
435 if (!Common::FS::Exists(main_url)) { 429 if (!Common::FS::Exists(main_url)) {
436 offline_romfs = GetOfflineRomFS(system, title_id, nca_type); 430 offline_romfs = GetOfflineRomFS(system, title_id, nca_type);
@@ -444,10 +438,11 @@ void WebBrowser::ExecuteOffline() {
444 } 438 }
445 } 439 }
446 440
447 LOG_INFO(Service_AM, "Opening offline document at {}", offline_document); 441 LOG_INFO(Service_AM, "Opening offline document at {}",
442 Common::FS::PathToUTF8String(offline_document));
448 443
449 frontend.OpenLocalWebPage( 444 frontend.OpenLocalWebPage(
450 offline_document, [this] { ExtractOfflineRomFS(); }, 445 Common::FS::PathToUTF8String(offline_document), [this] { ExtractOfflineRomFS(); },
451 [this](WebExitReason exit_reason, std::string last_url) { 446 [this](WebExitReason exit_reason, std::string last_url) {
452 WebBrowserExit(exit_reason, last_url); 447 WebBrowserExit(exit_reason, last_url);
453 }); 448 });
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index 1e1812f36..cdeaf2c40 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <filesystem>
7#include <optional> 8#include <optional>
8 9
9#include "common/common_funcs.h" 10#include "common/common_funcs.h"
@@ -75,8 +76,8 @@ private:
75 76
76 u64 title_id{}; 77 u64 title_id{};
77 FileSys::ContentRecordType nca_type{}; 78 FileSys::ContentRecordType nca_type{};
78 std::string offline_cache_dir; 79 std::filesystem::path offline_cache_dir;
79 std::string offline_document; 80 std::filesystem::path offline_document;
80 FileSys::VirtualFile offline_romfs; 81 FileSys::VirtualFile offline_romfs;
81 82
82 std::string external_url; 83 std::string external_url;
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index d6d2f52e5..3cc397604 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -15,6 +15,9 @@
15#pragma GCC diagnostic pop 15#pragma GCC diagnostic pop
16#endif 16#endif
17 17
18#include "common/fs/file.h"
19#include "common/fs/fs.h"
20#include "common/fs/path_util.h"
18#include "common/hex_util.h" 21#include "common/hex_util.h"
19#include "common/logging/backend.h" 22#include "common/logging/backend.h"
20#include "common/logging/log.h" 23#include "common/logging/log.h"
@@ -96,14 +99,14 @@ constexpr u32 PORT = 443;
96constexpr u32 TIMEOUT_SECONDS = 30; 99constexpr u32 TIMEOUT_SECONDS = 30;
97[[maybe_unused]] constexpr u64 VFS_COPY_BLOCK_SIZE = 1ULL << 24; // 4MB 100[[maybe_unused]] constexpr u64 VFS_COPY_BLOCK_SIZE = 1ULL << 24; // 4MB
98 101
99std::string GetBINFilePath(u64 title_id) { 102std::filesystem::path GetBINFilePath(u64 title_id) {
100 return fmt::format("{}bcat/{:016X}/launchparam.bin", 103 return Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "bcat" /
101 Common::FS::GetUserPath(Common::FS::UserPath::CacheDir), title_id); 104 fmt::format("{:016X}/launchparam.bin", title_id);
102} 105}
103 106
104std::string GetZIPFilePath(u64 title_id) { 107std::filesystem::path GetZIPFilePath(u64 title_id) {
105 return fmt::format("{}bcat/{:016X}/data.zip", 108 return Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "bcat" /
106 Common::FS::GetUserPath(Common::FS::UserPath::CacheDir), title_id); 109 fmt::format("{:016X}/data.zip", title_id);
107} 110}
108 111
109// If the error is something the user should know about (build ID mismatch, bad client version), 112// If the error is something the user should know about (build ID mismatch, bad client version),
@@ -187,7 +190,7 @@ bool VfsRawCopyDProgress(FileSys::VirtualDir src, FileSys::VirtualDir dest,
187 190
188class Boxcat::Client { 191class Boxcat::Client {
189public: 192public:
190 Client(std::string path_, u64 title_id_, u64 build_id_) 193 Client(std::filesystem::path path_, u64 title_id_, u64 build_id_)
191 : path(std::move(path_)), title_id(title_id_), build_id(build_id_) {} 194 : path(std::move(path_)), title_id(title_id_), build_id(build_id_) {}
192 195
193 DownloadResult DownloadDataZip() { 196 DownloadResult DownloadDataZip() {
@@ -217,10 +220,11 @@ private:
217 }; 220 };
218 221
219 if (Common::FS::Exists(path)) { 222 if (Common::FS::Exists(path)) {
220 Common::FS::IOFile file{path, "rb"}; 223 Common::FS::IOFile file{path, Common::FS::FileAccessMode::Read,
224 Common::FS::FileType::BinaryFile};
221 if (file.IsOpen()) { 225 if (file.IsOpen()) {
222 std::vector<u8> bytes(file.GetSize()); 226 std::vector<u8> bytes(file.GetSize());
223 file.ReadBytes(bytes.data(), bytes.size()); 227 void(file.Read(bytes));
224 const auto digest = DigestFile(bytes); 228 const auto digest = DigestFile(bytes);
225 headers.insert({std::string("If-None-Match"), Common::HexToString(digest, false)}); 229 headers.insert({std::string("If-None-Match"), Common::HexToString(digest, false)});
226 } 230 }
@@ -247,14 +251,23 @@ private:
247 return DownloadResult::InvalidContentType; 251 return DownloadResult::InvalidContentType;
248 } 252 }
249 253
250 Common::FS::CreateFullPath(path); 254 if (!Common::FS::CreateDirs(path)) {
251 Common::FS::IOFile file{path, "wb"};
252 if (!file.IsOpen())
253 return DownloadResult::GeneralFSError; 255 return DownloadResult::GeneralFSError;
254 if (!file.Resize(response->body.size())) 256 }
257
258 Common::FS::IOFile file{path, Common::FS::FileAccessMode::Append,
259 Common::FS::FileType::BinaryFile};
260 if (!file.IsOpen()) {
261 return DownloadResult::GeneralFSError;
262 }
263
264 if (!file.SetSize(response->body.size())) {
255 return DownloadResult::GeneralFSError; 265 return DownloadResult::GeneralFSError;
256 if (file.WriteBytes(response->body.data(), response->body.size()) != response->body.size()) 266 }
267
268 if (file.Write(response->body) != response->body.size()) {
257 return DownloadResult::GeneralFSError; 269 return DownloadResult::GeneralFSError;
270 }
258 271
259 return DownloadResult::Success; 272 return DownloadResult::Success;
260 } 273 }
@@ -267,7 +280,7 @@ private:
267 } 280 }
268 281
269 std::unique_ptr<httplib::SSLClient> client; 282 std::unique_ptr<httplib::SSLClient> client;
270 std::string path; 283 std::filesystem::path path;
271 u64 title_id; 284 u64 title_id;
272 u64 build_id; 285 u64 build_id;
273}; 286};
@@ -291,7 +304,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe
291 return; 304 return;
292 } 305 }
293 306
294 const auto zip_path{GetZIPFilePath(title.title_id)}; 307 const auto zip_path = GetZIPFilePath(title.title_id);
295 Boxcat::Client client{zip_path, title.title_id, title.build_id}; 308 Boxcat::Client client{zip_path, title.title_id, title.build_id};
296 309
297 progress.StartConnecting(); 310 progress.StartConnecting();
@@ -301,7 +314,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe
301 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); 314 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
302 315
303 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { 316 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
304 Common::FS::Delete(zip_path); 317 void(Common::FS::RemoveFile(zip_path));
305 } 318 }
306 319
307 HandleDownloadDisplayResult(applet_manager, res); 320 HandleDownloadDisplayResult(applet_manager, res);
@@ -311,11 +324,13 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe
311 324
312 progress.StartProcessingDataList(); 325 progress.StartProcessingDataList();
313 326
314 Common::FS::IOFile zip{zip_path, "rb"}; 327 Common::FS::IOFile zip{zip_path, Common::FS::FileAccessMode::Read,
328 Common::FS::FileType::BinaryFile};
315 const auto size = zip.GetSize(); 329 const auto size = zip.GetSize();
316 std::vector<u8> bytes(size); 330 std::vector<u8> bytes(size);
317 if (!zip.IsOpen() || size == 0 || zip.ReadBytes(bytes.data(), bytes.size()) != bytes.size()) { 331 if (!zip.IsOpen() || size == 0 || zip.Read(bytes) != bytes.size()) {
318 LOG_ERROR(Service_BCAT, "Boxcat failed to read ZIP file at path '{}'!", zip_path); 332 LOG_ERROR(Service_BCAT, "Boxcat failed to read ZIP file at path '{}'!",
333 Common::FS::PathToUTF8String(zip_path));
319 progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE); 334 progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
320 return; 335 return;
321 } 336 }
@@ -419,19 +434,19 @@ void Boxcat::SetPassphrase(u64 title_id, const Passphrase& passphrase) {
419} 434}
420 435
421std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title) { 436std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title) {
422 const auto path{GetBINFilePath(title.title_id)}; 437 const auto bin_file_path = GetBINFilePath(title.title_id);
423 438
424 if (Settings::values.bcat_boxcat_local) { 439 if (Settings::values.bcat_boxcat_local) {
425 LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download."); 440 LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download.");
426 } else { 441 } else {
427 Client launch_client{path, title.title_id, title.build_id}; 442 Client launch_client{bin_file_path, title.title_id, title.build_id};
428 443
429 const auto res = launch_client.DownloadLaunchParam(); 444 const auto res = launch_client.DownloadLaunchParam();
430 if (res != DownloadResult::Success) { 445 if (res != DownloadResult::Success) {
431 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); 446 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
432 447
433 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { 448 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
434 Common::FS::Delete(path); 449 void(Common::FS::RemoveFile(bin_file_path));
435 } 450 }
436 451
437 HandleDownloadDisplayResult(applet_manager, res); 452 HandleDownloadDisplayResult(applet_manager, res);
@@ -439,12 +454,13 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title)
439 } 454 }
440 } 455 }
441 456
442 Common::FS::IOFile bin{path, "rb"}; 457 Common::FS::IOFile bin{bin_file_path, Common::FS::FileAccessMode::Read,
458 Common::FS::FileType::BinaryFile};
443 const auto size = bin.GetSize(); 459 const auto size = bin.GetSize();
444 std::vector<u8> bytes(size); 460 std::vector<u8> bytes(size);
445 if (!bin.IsOpen() || size == 0 || bin.ReadBytes(bytes.data(), bytes.size()) != bytes.size()) { 461 if (!bin.IsOpen() || size == 0 || bin.Read(bytes) != bytes.size()) {
446 LOG_ERROR(Service_BCAT, "Boxcat failed to read launch parameter binary at path '{}'!", 462 LOG_ERROR(Service_BCAT, "Boxcat failed to read launch parameter binary at path '{}'!",
447 path); 463 Common::FS::PathToUTF8String(bin_file_path));
448 return std::nullopt; 464 return std::nullopt;
449 } 465 }
450 466
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index 432abde76..b7666e95a 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -6,7 +6,6 @@
6#include <cstring> 6#include <cstring>
7#include <ctime> 7#include <ctime>
8#include <fmt/chrono.h> 8#include <fmt/chrono.h>
9#include "common/file_util.h"
10#include "common/logging/log.h" 9#include "common/logging/log.h"
11#include "common/scm_rev.h" 10#include "common/scm_rev.h"
12#include "common/swap.h" 11#include "common/swap.h"
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 67baaee9b..78664439d 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -5,7 +5,7 @@
5#include <utility> 5#include <utility>
6 6
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/file_util.h" 8#include "common/fs/path_util.h"
9#include "common/settings.h" 9#include "common/settings.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/file_sys/bis_factory.h" 11#include "core/file_sys/bis_factory.h"
@@ -728,14 +728,17 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
728 sdmc_factory = nullptr; 728 sdmc_factory = nullptr;
729 } 729 }
730 730
731 auto nand_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir), 731 using YuzuPath = Common::FS::YuzuPath;
732 FileSys::Mode::ReadWrite); 732 const auto rw_mode = FileSys::Mode::ReadWrite;
733 auto sd_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir), 733
734 FileSys::Mode::ReadWrite); 734 auto nand_directory =
735 auto load_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::LoadDir), 735 vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode);
736 FileSys::Mode::ReadWrite); 736 auto sd_directory =
737 auto dump_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::DumpDir), 737 vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::SDMCDir), rw_mode);
738 FileSys::Mode::ReadWrite); 738 auto load_directory =
739 vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::LoadDir), FileSys::Mode::Read);
740 auto dump_directory =
741 vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::DumpDir), rw_mode);
739 742
740 if (bis_factory == nullptr) { 743 if (bis_factory == nullptr) {
741 bis_factory = 744 bis_factory =
diff --git a/src/core/hle/service/mii/manager.cpp b/src/core/hle/service/mii/manager.cpp
index 70350a2a3..114aff31c 100644
--- a/src/core/hle/service/mii/manager.cpp
+++ b/src/core/hle/service/mii/manager.cpp
@@ -6,7 +6,6 @@
6#include <random> 6#include <random>
7 7
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/file_util.h"
10#include "common/logging/log.h" 9#include "common/logging/log.h"
11#include "common/string_util.h" 10#include "common/string_util.h"
12 11
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index e14acce58..90ba5c752 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -7,9 +7,7 @@
7#include <vector> 7#include <vector>
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/common_paths.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "common/file_util.h"
13#include "common/logging/log.h" 11#include "common/logging/log.h"
14#include "common/swap.h" 12#include "common/swap.h"
15#include "core/core.h" 13#include "core/core.h"
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 022885c1b..a19bb220a 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -5,7 +5,6 @@
5#include <cinttypes> 5#include <cinttypes>
6#include <cstring> 6#include <cstring>
7#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/file_util.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10#include "core/core.h" 9#include "core/core.h"
11#include "core/file_sys/content_archive.h" 10#include "core/file_sys/content_archive.h"
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index c062a4259..3d9276f15 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -7,7 +7,6 @@
7#include <string> 7#include <string>
8#include "common/common_funcs.h" 8#include "common/common_funcs.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/file_util.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "core/hle/kernel/code_set.h" 11#include "core/hle/kernel/code_set.h"
13#include "core/hle/kernel/k_page_table.h" 12#include "core/hle/kernel/k_page_table.h"
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index d4808fb5b..228dc6389 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -7,7 +7,7 @@
7#include <ostream> 7#include <ostream>
8#include <string> 8#include <string>
9#include "common/concepts.h" 9#include "common/concepts.h"
10#include "common/file_util.h" 10#include "common/fs/path_util.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/string_util.h" 12#include "common/string_util.h"
13#include "core/core.h" 13#include "core/core.h"
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index 418cbf61b..aa51b0daa 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -4,7 +4,6 @@
4 4
5#include <utility> 5#include <utility>
6 6
7#include "common/file_util.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9#include "core/core.h" 8#include "core/core.h"
10#include "core/file_sys/content_archive.h" 9#include "core/file_sys/content_archive.h"
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index ef54fa574..618555202 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -7,7 +7,6 @@
7 7
8#include "common/common_funcs.h" 8#include "common/common_funcs.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/file_util.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/settings.h" 11#include "common/settings.h"
13#include "common/swap.h" 12#include "common/swap.h"
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index df59412cf..0f5cfda68 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -7,7 +7,6 @@
7#include <vector> 7#include <vector>
8 8
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
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/lz4_compression.h" 12#include "common/lz4_compression.h"
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index c42c437b7..6635a1339 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -11,7 +11,9 @@
11#include <thread> 11#include <thread>
12#include <fmt/chrono.h> 12#include <fmt/chrono.h>
13#include <fmt/format.h> 13#include <fmt/format.h>
14#include "common/file_util.h" 14#include "common/fs/file.h"
15#include "common/fs/fs.h"
16#include "common/fs/path_util.h"
15#include "common/math_util.h" 17#include "common/math_util.h"
16#include "common/settings.h" 18#include "common/settings.h"
17#include "core/perf_stats.h" 19#include "core/perf_stats.h"
@@ -38,12 +40,17 @@ PerfStats::~PerfStats() {
38 std::ostringstream stream; 40 std::ostringstream stream;
39 std::copy(perf_history.begin() + IgnoreFrames, perf_history.begin() + current_index, 41 std::copy(perf_history.begin() + IgnoreFrames, perf_history.begin() + current_index,
40 std::ostream_iterator<double>(stream, "\n")); 42 std::ostream_iterator<double>(stream, "\n"));
41 const std::string& path = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); 43
44 const auto path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir);
42 // %F Date format expanded is "%Y-%m-%d" 45 // %F Date format expanded is "%Y-%m-%d"
43 const std::string filename = 46 const auto filename = fmt::format("{:%F-%H-%M}_{:016X}.csv", *std::localtime(&t), title_id);
44 fmt::format("{}/{:%F-%H-%M}_{:016X}.csv", path, *std::localtime(&t), title_id); 47 const auto filepath = path / filename;
45 Common::FS::IOFile file(filename, "w"); 48
46 file.WriteString(stream.str()); 49 if (Common::FS::CreateParentDir(filepath)) {
50 Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Write,
51 Common::FS::FileType::TextFile);
52 void(file.WriteString(stream.str()));
53 }
47} 54}
48 55
49void PerfStats::BeginSystemFrame() { 56void PerfStats::BeginSystemFrame() {
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index d1e807dd4..a9596fe4d 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -11,7 +11,9 @@
11#include <fmt/ostream.h> 11#include <fmt/ostream.h>
12#include <nlohmann/json.hpp> 12#include <nlohmann/json.hpp>
13 13
14#include "common/file_util.h" 14#include "common/fs/file.h"
15#include "common/fs/fs.h"
16#include "common/fs/path_util.h"
15#include "common/hex_util.h" 17#include "common/hex_util.h"
16#include "common/scm_rev.h" 18#include "common/scm_rev.h"
17#include "common/settings.h" 19#include "common/settings.h"
@@ -26,10 +28,9 @@
26 28
27namespace { 29namespace {
28 30
29std::string GetPath(std::string_view type, u64 title_id, std::string_view timestamp) { 31std::filesystem::path GetPath(std::string_view type, u64 title_id, std::string_view timestamp) {
30 return fmt::format("{}{}/{:016X}_{}.json", 32 return Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir) / type /
31 Common::FS::GetUserPath(Common::FS::UserPath::LogDir), type, title_id, 33 fmt::format("{:016X}_{}.json", title_id, timestamp);
32 timestamp);
33} 34}
34 35
35std::string GetTimestamp() { 36std::string GetTimestamp() {
@@ -39,14 +40,16 @@ std::string GetTimestamp() {
39 40
40using namespace nlohmann; 41using namespace nlohmann;
41 42
42void SaveToFile(json json, const std::string& filename) { 43void SaveToFile(json json, const std::filesystem::path& filename) {
43 if (!Common::FS::CreateFullPath(filename)) { 44 if (!Common::FS::CreateParentDirs(filename)) {
44 LOG_ERROR(Core, "Failed to create path for '{}' to save report!", filename); 45 LOG_ERROR(Core, "Failed to create path for '{}' to save report!",
46 Common::FS::PathToUTF8String(filename));
45 return; 47 return;
46 } 48 }
47 49
48 std::ofstream file( 50 std::ofstream file;
49 Common::FS::SanitizePath(filename, Common::FS::DirectorySeparator::PlatformDefault)); 51 Common::FS::OpenFileStream(file, filename, std::ios_base::out | std::ios_base::trunc);
52
50 file << std::setw(4) << json << std::endl; 53 file << std::setw(4) << json << std::endl;
51} 54}
52 55
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index 6dcff5400..ad1a9ffb4 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -9,7 +9,9 @@
9 9
10#include "common/assert.h" 10#include "common/assert.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/file_util.h" 12#include "common/fs/file.h"
13#include "common/fs/fs.h"
14#include "common/fs/path_util.h"
13#include "common/logging/log.h" 15#include "common/logging/log.h"
14 16
15#include "common/settings.h" 17#include "common/settings.h"
@@ -72,31 +74,41 @@ static const char* TranslateGPUAccuracyLevel(Settings::GPUAccuracy backend) {
72 74
73u64 GetTelemetryId() { 75u64 GetTelemetryId() {
74 u64 telemetry_id{}; 76 u64 telemetry_id{};
75 const std::string filename{Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir) + 77 const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id";
76 "telemetry_id"};
77 78
78 bool generate_new_id = !Common::FS::Exists(filename); 79 bool generate_new_id = !Common::FS::Exists(filename);
80
79 if (!generate_new_id) { 81 if (!generate_new_id) {
80 Common::FS::IOFile file(filename, "rb"); 82 Common::FS::IOFile file{filename, Common::FS::FileAccessMode::Read,
83 Common::FS::FileType::BinaryFile};
84
81 if (!file.IsOpen()) { 85 if (!file.IsOpen()) {
82 LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); 86 LOG_ERROR(Core, "failed to open telemetry_id: {}",
87 Common::FS::PathToUTF8String(filename));
83 return {}; 88 return {};
84 } 89 }
85 file.ReadBytes(&telemetry_id, sizeof(u64)); 90
86 if (telemetry_id == 0) { 91 if (!file.ReadObject(telemetry_id) || telemetry_id == 0) {
87 LOG_ERROR(Frontend, "telemetry_id is 0. Generating a new one.", telemetry_id); 92 LOG_ERROR(Frontend, "telemetry_id is 0. Generating a new one.", telemetry_id);
88 generate_new_id = true; 93 generate_new_id = true;
89 } 94 }
90 } 95 }
91 96
92 if (generate_new_id) { 97 if (generate_new_id) {
93 Common::FS::IOFile file(filename, "wb"); 98 Common::FS::IOFile file{filename, Common::FS::FileAccessMode::Write,
99 Common::FS::FileType::BinaryFile};
100
94 if (!file.IsOpen()) { 101 if (!file.IsOpen()) {
95 LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); 102 LOG_ERROR(Core, "failed to open telemetry_id: {}",
103 Common::FS::PathToUTF8String(filename));
96 return {}; 104 return {};
97 } 105 }
106
98 telemetry_id = GenerateTelemetryId(); 107 telemetry_id = GenerateTelemetryId();
99 file.WriteBytes(&telemetry_id, sizeof(u64)); 108
109 if (!file.WriteObject(telemetry_id)) {
110 LOG_ERROR(Core, "Failed to write telemetry_id to file.");
111 }
100 } 112 }
101 113
102 return telemetry_id; 114 return telemetry_id;
@@ -104,15 +116,20 @@ u64 GetTelemetryId() {
104 116
105u64 RegenerateTelemetryId() { 117u64 RegenerateTelemetryId() {
106 const u64 new_telemetry_id{GenerateTelemetryId()}; 118 const u64 new_telemetry_id{GenerateTelemetryId()};
107 const std::string filename{Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir) + 119 const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id";
108 "telemetry_id"}; 120
121 Common::FS::IOFile file{filename, Common::FS::FileAccessMode::Write,
122 Common::FS::FileType::BinaryFile};
109 123
110 Common::FS::IOFile file(filename, "wb");
111 if (!file.IsOpen()) { 124 if (!file.IsOpen()) {
112 LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); 125 LOG_ERROR(Core, "failed to open telemetry_id: {}", Common::FS::PathToUTF8String(filename));
113 return {}; 126 return {};
114 } 127 }
115 file.WriteBytes(&new_telemetry_id, sizeof(u64)); 128
129 if (!file.WriteObject(new_telemetry_id)) {
130 LOG_ERROR(Core, "Failed to write telemetry_id to file.");
131 }
132
116 return new_telemetry_id; 133 return new_telemetry_id;
117} 134}
118 135