summaryrefslogtreecommitdiff
path: root/src/core/hle/service
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/hle/service
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/hle/service')
-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
9 files changed, 111 insertions, 95 deletions
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"