From 8317a66ea5c4224a2a6ccfb2389f3b5fe7efff13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 8 Apr 2018 11:57:36 +0200 Subject: [PATCH] NandPaths: Return paths that are relative to Wii NAND Since all FS access will go through the new FS interface (PR #6421) in order to keep track of metadata properly, there is no need to return absolute paths anymore. In fact, returning host paths is a roadblock to using the FS interface. This starts the migration work by adding a way to get paths that are relative to the Wii NAND instead of always getting absolute paths on the host FS. To prepare for future changes, this commit also makes returned paths canonical by removing the trailing slash when it's unneeded. Eventually, once everything has been migrated to the new interface, we can remove the "from" parameter. --- Source/Core/Common/NandPaths.cpp | 27 +++++++++++-------- Source/Core/Common/NandPaths.h | 22 +++++++++------ Source/Core/Core/Boot/Boot.cpp | 2 +- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 4 +-- Source/Core/Core/HW/WiiSaveCrypted.cpp | 8 +++--- Source/Core/Core/IOS/ES/NandUtils.cpp | 17 +++++++----- Source/Core/Core/IOS/ES/TitleManagement.cpp | 5 ++-- .../Core/Core/IOS/Network/KD/NetKDRequest.cpp | 3 ++- Source/Core/Core/Movie.cpp | 4 +-- Source/Core/Core/WiiRoot.cpp | 8 +++--- Source/Core/DiscIO/WiiSaveBanner.cpp | 3 ++- 11 files changed, 61 insertions(+), 42 deletions(-) diff --git a/Source/Core/Common/NandPaths.cpp b/Source/Core/Common/NandPaths.cpp index b670be635d..336c1bb7bb 100644 --- a/Source/Core/Common/NandPaths.cpp +++ b/Source/Core/Common/NandPaths.cpp @@ -21,41 +21,46 @@ std::string RootUserPath(FromWhichRoot from) return File::GetUserPath(idx); } -std::string GetImportTitlePath(u64 title_id, FromWhichRoot from) +static std::string RootUserPath(std::optional from) +{ + return from ? RootUserPath(*from) : ""; +} + +std::string GetImportTitlePath(u64 title_id, std::optional from) { return RootUserPath(from) + StringFromFormat("/import/%08x/%08x", static_cast(title_id >> 32), static_cast(title_id)); } -std::string GetTicketFileName(u64 title_id, FromWhichRoot from) +std::string GetTicketFileName(u64 title_id, std::optional from) { return StringFromFormat("%s/ticket/%08x/%08x.tik", RootUserPath(from).c_str(), static_cast(title_id >> 32), static_cast(title_id)); } -std::string GetTitlePath(u64 title_id, FromWhichRoot from) +std::string GetTitlePath(u64 title_id, std::optional from) { - return StringFromFormat("%s/title/%08x/%08x/", RootUserPath(from).c_str(), + return StringFromFormat("%s/title/%08x/%08x", RootUserPath(from).c_str(), static_cast(title_id >> 32), static_cast(title_id)); } -std::string GetTitleDataPath(u64 title_id, FromWhichRoot from) +std::string GetTitleDataPath(u64 title_id, std::optional from) { - return GetTitlePath(title_id, from) + "data/"; + return GetTitlePath(title_id, from) + "/data"; } -std::string GetTitleContentPath(u64 title_id, FromWhichRoot from) +std::string GetTitleContentPath(u64 title_id, std::optional from) { - return GetTitlePath(title_id, from) + "content/"; + return GetTitlePath(title_id, from) + "/content"; } -std::string GetTMDFileName(u64 title_id, FromWhichRoot from) +std::string GetTMDFileName(u64 title_id, std::optional from) { - return GetTitleContentPath(title_id, from) + "title.tmd"; + return GetTitleContentPath(title_id, from) + "/title.tmd"; } -bool IsTitlePath(const std::string& path, FromWhichRoot from, u64* title_id) +bool IsTitlePath(const std::string& path, std::optional from, u64* title_id) { std::string expected_prefix = RootUserPath(from) + "/title/"; if (!StringBeginsWith(path, expected_prefix)) diff --git a/Source/Core/Common/NandPaths.h b/Source/Core/Common/NandPaths.h index 5a1dcffce4..068a240f43 100644 --- a/Source/Core/Common/NandPaths.h +++ b/Source/Core/Common/NandPaths.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "Common/CommonTypes.h" @@ -18,17 +19,22 @@ enum FromWhichRoot std::string RootUserPath(FromWhichRoot from); -// Returns /import/%08x/%08x. Intended for use by ES. -std::string GetImportTitlePath(u64 title_id, FromWhichRoot from = FROM_SESSION_ROOT); +// The following functions return paths relative to the NAND root. +// If a FromWhichRoot is passed, the NAND root on the host filesystem will be prepended to the path. +// TODO: remove the from parameter after all code is migrated off direct FS access. -std::string GetTicketFileName(u64 title_id, FromWhichRoot from); -std::string GetTitlePath(u64 title_id, FromWhichRoot from); -std::string GetTitleDataPath(u64 title_id, FromWhichRoot from); -std::string GetTitleContentPath(u64 title_id, FromWhichRoot from); -std::string GetTMDFileName(u64 title_id, FromWhichRoot from); +// Returns /import/%08x/%08x. Intended for use by ES. +std::string GetImportTitlePath(u64 title_id, std::optional from = {}); + +std::string GetTicketFileName(u64 title_id, std::optional from = {}); +std::string GetTitlePath(u64 title_id, std::optional from = {}); +std::string GetTitleDataPath(u64 title_id, std::optional from = {}); +std::string GetTitleContentPath(u64 title_id, std::optional from = {}); +std::string GetTMDFileName(u64 title_id, std::optional from = {}); // Returns whether a path is within an installed title's directory. -bool IsTitlePath(const std::string& path, FromWhichRoot from, u64* title_id = nullptr); +bool IsTitlePath(const std::string& path, std::optional from = {}, + u64* title_id = nullptr); // Escapes characters that are invalid or have special meanings in the host file system std::string EscapeFileName(const std::string& filename); diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index f93b584251..d38ec6ad59 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -472,7 +472,7 @@ void StateFlags::UpdateChecksum() void UpdateStateFlags(std::function update_function) { const std::string file_path = - Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + WII_STATE; + Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + "/" WII_STATE; File::IOFile file; StateFlags state; diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index f426175e58..dc4d5b91e8 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -227,7 +227,7 @@ bool CBoot::SetupWiiMemory() SettingsHandler gen; std::string serno; const std::string settings_file_path( - Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + WII_SETTING); + Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + "/" WII_SETTING); if (File::Exists(settings_file_path) && gen.Open(settings_file_path)) { serno = gen.GetValue("SERNO"); @@ -328,7 +328,7 @@ bool CBoot::SetupWiiMemory() static void WriteEmptyPlayRecord() { const std::string file_path = - Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + "play_rec.dat"; + Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + "/play_rec.dat"; File::IOFile playrec_file(file_path, "r+b"); std::vector empty_record(0x80); playrec_file.WriteBytes(empty_record.data(), empty_record.size()); diff --git a/Source/Core/Core/HW/WiiSaveCrypted.cpp b/Source/Core/Core/HW/WiiSaveCrypted.cpp index 835ff9b980..28c9150b34 100644 --- a/Source/Core/Core/HW/WiiSaveCrypted.cpp +++ b/Source/Core/Core/HW/WiiSaveCrypted.cpp @@ -181,7 +181,7 @@ void CWiiSaveCrypted::ReadHDR() m_valid = false; return; } - std::string banner_file_path = m_wii_title_path + "banner.bin"; + std::string banner_file_path = m_wii_title_path + "/banner.bin"; if (!File::Exists(banner_file_path) || AskYesNoT("%s already exists. Consider making a backup of the current save files before " "overwriting.\nOverwrite now?", @@ -203,7 +203,7 @@ void CWiiSaveCrypted::WriteHDR() return; memset(&m_header, 0, HEADER_SZ); - std::string banner_file_path = m_wii_title_path + "banner.bin"; + std::string banner_file_path = m_wii_title_path + "/banner.bin"; u32 banner_size = static_cast(File::GetSize(banner_file_path)); m_header.hdr.BannerSize = Common::swap32(banner_size); @@ -347,7 +347,7 @@ void CWiiSaveCrypted::ImportWiiSaveFiles() // Special characters in path components will be escaped such as /../ std::string file_path = Common::EscapePath(reinterpret_cast(file_hdr_tmp.name)); - std::string file_path_full = m_wii_title_path + file_path; + std::string file_path_full = m_wii_title_path + '/' + file_path; File::CreateFullPath(file_path_full); const File::FileInfo file_info(file_path_full); if (file_hdr_tmp.type == 1) @@ -585,7 +585,7 @@ bool CWiiSaveCrypted::getPaths(bool for_export) return false; } - if (!File::Exists(m_wii_title_path + "banner.bin")) + if (!File::Exists(m_wii_title_path + "/banner.bin")) { m_valid = false; ERROR_LOG(CONSOLE, "No banner file found for title %s", game_id); diff --git a/Source/Core/Core/IOS/ES/NandUtils.cpp b/Source/Core/Core/IOS/ES/NandUtils.cpp index 06c6efdf29..1b332bf97b 100644 --- a/Source/Core/Core/IOS/ES/NandUtils.cpp +++ b/Source/Core/Core/IOS/ES/NandUtils.cpp @@ -42,7 +42,8 @@ static IOS::ES::TMDReader FindTMD(u64 title_id, const std::string& tmd_path) IOS::ES::TMDReader ES::FindImportTMD(u64 title_id) const { - return FindTMD(title_id, Common::GetImportTitlePath(title_id) + "/content/title.tmd"); + return FindTMD(title_id, Common::GetImportTitlePath(title_id, Common::FROM_SESSION_ROOT) + + "/content/title.tmd"); } IOS::ES::TMDReader ES::FindInstalledTMD(u64 title_id) const @@ -218,7 +219,8 @@ bool ES::InitImport(u64 title_id) // IOS moves the title content directory to /import if the TMD exists during an import. if (File::Exists(Common::GetTMDFileName(title_id, Common::FROM_SESSION_ROOT))) { - const std::string import_content_dir = Common::GetImportTitlePath(title_id) + "/content"; + const std::string import_content_dir = + Common::GetImportTitlePath(title_id, Common::FROM_SESSION_ROOT) + "/content"; File::CreateFullPath(import_content_dir); if (!File::Rename(content_dir, import_content_dir)) { @@ -233,7 +235,8 @@ bool ES::InitImport(u64 title_id) bool ES::FinishImport(const IOS::ES::TMDReader& tmd) { const u64 title_id = tmd.GetTitleId(); - const std::string import_content_dir = Common::GetImportTitlePath(title_id) + "/content"; + const std::string import_content_dir = + Common::GetImportTitlePath(title_id, Common::FROM_SESSION_ROOT) + "/content"; // Remove everything not listed in the TMD. std::unordered_set expected_entries = {"title.tmd"}; @@ -274,7 +277,8 @@ bool ES::WriteImportTMD(const IOS::ES::TMDReader& tmd) return false; } - const std::string dest = Common::GetImportTitlePath(tmd.GetTitleId()) + "/content/title.tmd"; + const std::string dest = Common::GetImportTitlePath(tmd.GetTitleId(), Common::FROM_SESSION_ROOT) + + "/content/title.tmd"; return File::Rename(tmd_path, dest); } @@ -282,7 +286,8 @@ void ES::FinishStaleImport(u64 title_id) { const auto import_tmd = FindImportTMD(title_id); if (!import_tmd.IsValid()) - File::DeleteDirRecursively(Common::GetImportTitlePath(title_id) + "/content"); + File::DeleteDirRecursively(Common::GetImportTitlePath(title_id, Common::FROM_SESSION_ROOT) + + "/content"); else FinishImport(import_tmd); } @@ -305,7 +310,7 @@ std::string ES::GetContentPath(const u64 title_id, const IOS::ES::Content& conte return content_map.GetFilenameFromSHA1(content.sha1).value_or(""); return Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT) + - StringFromFormat("%08x.app", content.id); + StringFromFormat("/%08x.app", content.id); } } // namespace Device } // namespace HLE diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index 2496f854f7..1bb9a1a752 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -342,7 +342,8 @@ static bool CheckIfContentHashMatches(const std::vector& content, const IOS: static std::string GetImportContentPath(u64 title_id, u32 content_id) { - return Common::GetImportTitlePath(title_id) + StringFromFormat("/content/%08x.app", content_id); + return Common::GetImportTitlePath(title_id, Common::FROM_SESSION_ROOT) + + StringFromFormat("/content/%08x.app", content_id); } ReturnCode ES::ImportContentEnd(Context& context, u32 content_fd) @@ -604,7 +605,7 @@ ReturnCode ES::DeleteContent(u64 title_id, u32 content_id) const return ES_EINVAL; if (!File::Delete(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT) + - StringFromFormat("%08x.app", content_id))) + StringFromFormat("/%08x.app", content_id))) { return FS_ENOENT; } diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp index a36ccf537a..ce3f202ddc 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp @@ -83,7 +83,8 @@ IPCCommandResult NetKDRequest::IOCtl(const IOCtlRequest& request) if (config.CreationStage() == NWC24::NWC24Config::NWC24_IDCS_INITIAL) { const std::string settings_file_path( - Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + WII_SETTING); + Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + + "/" WII_SETTING); SettingsHandler gen; std::string area, model; bool got_settings = false; diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index bf3b0c099f..980e75ee82 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -1384,8 +1384,8 @@ void GetSettings() if (SConfig::GetInstance().bWii) { u64 title_id = SConfig::GetInstance().GetTitleID(); - s_bClearSave = - !File::Exists(Common::GetTitleDataPath(title_id, Common::FROM_SESSION_ROOT) + "banner.bin"); + s_bClearSave = !File::Exists(Common::GetTitleDataPath(title_id, Common::FROM_SESSION_ROOT) + + "/banner.bin"); } else { diff --git a/Source/Core/Core/WiiRoot.cpp b/Source/Core/Core/WiiRoot.cpp index a705801fc1..8058ab2685 100644 --- a/Source/Core/Core/WiiRoot.cpp +++ b/Source/Core/Core/WiiRoot.cpp @@ -36,7 +36,7 @@ static void InitializeDeterministicWiiSaves() else { // TODO: Check for the actual save data - Movie::SetClearSave(!File::Exists(user_save_path + "banner.bin")); + Movie::SetClearSave(!File::Exists(user_save_path + "/banner.bin")); } } @@ -44,7 +44,7 @@ static void InitializeDeterministicWiiSaves() (Movie::IsMovieActive() && !Movie::IsStartingFromClearSave())) { // Copy the current user's save to the Blank NAND - if (File::Exists(user_save_path + "banner.bin")) + if (File::Exists(user_save_path + "/banner.bin")) { File::CopyDir(user_save_path, save_path); } @@ -86,10 +86,10 @@ void ShutdownWiiRoot() std::string user_backup_path = File::GetUserPath(D_BACKUP_IDX) + StringFromFormat("%08x/%08x/", static_cast(title_id >> 32), static_cast(title_id)); - if (File::Exists(save_path + "banner.bin") && SConfig::GetInstance().bEnableMemcardSdWriting) + if (File::Exists(save_path + "/banner.bin") && SConfig::GetInstance().bEnableMemcardSdWriting) { // Backup the existing save just in case it's still needed. - if (File::Exists(user_save_path + "banner.bin")) + if (File::Exists(user_save_path + "/banner.bin")) { if (File::Exists(user_backup_path)) File::DeleteDirRecursively(user_backup_path); diff --git a/Source/Core/DiscIO/WiiSaveBanner.cpp b/Source/Core/DiscIO/WiiSaveBanner.cpp index a248151e44..444cb0590d 100644 --- a/Source/Core/DiscIO/WiiSaveBanner.cpp +++ b/Source/Core/DiscIO/WiiSaveBanner.cpp @@ -25,7 +25,8 @@ constexpr unsigned int ICON_HEIGHT = 48; constexpr unsigned int ICON_SIZE = ICON_WIDTH * ICON_HEIGHT * 2; WiiSaveBanner::WiiSaveBanner(u64 title_id) - : WiiSaveBanner(Common::GetTitleDataPath(title_id, Common::FROM_CONFIGURED_ROOT) + "banner.bin") + : WiiSaveBanner(Common::GetTitleDataPath(title_id, Common::FROM_CONFIGURED_ROOT) + + "/banner.bin") { }