diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index 8cbde024ac..30d15d23e0 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -13,8 +13,6 @@ #include #include "Common/Align.h" -#include "Common/File.h" -#include "Common/FileUtil.h" #include "Common/Logging/Log.h" #include "Common/NandPaths.h" #include "Common/StringUtil.h" @@ -29,19 +27,22 @@ namespace HLE { namespace Device { -static ReturnCode WriteTicket(const IOS::ES::TicketReader& ticket) +static ReturnCode WriteTicket(FS::FileSystem* fs, const IOS::ES::TicketReader& ticket) { const u64 title_id = ticket.GetTitleId(); - const std::string ticket_path = Common::GetTicketFileName(title_id, Common::FROM_SESSION_ROOT); - File::CreateFullPath(ticket_path); + const std::string path = Common::GetTicketFileName(title_id); + fs->CreateFullPath(PID_KERNEL, PID_KERNEL, path, 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, + FS::Mode::None); + fs->CreateFile(PID_KERNEL, PID_KERNEL, path, 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, + FS::Mode::None); - File::IOFile ticket_file(ticket_path, "wb"); - if (!ticket_file) - return ES_EIO; + const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, path, FS::Mode::Write); + if (!file) + return FS::ConvertResult(file.Error()); const std::vector& raw_ticket = ticket.GetBytes(); - return ticket_file.WriteBytes(raw_ticket.data(), raw_ticket.size()) ? IPC_SUCCESS : ES_EIO; + return file->Write(raw_ticket.data(), raw_ticket.size()) ? IPC_SUCCESS : ES_EIO; } void ES::TitleImportExportContext::DoState(PointerWrap& p) @@ -85,7 +86,7 @@ ReturnCode ES::ImportTicket(const std::vector& ticket_bytes, const std::vect if (verify_ret != IPC_SUCCESS) return verify_ret; - const ReturnCode write_ret = WriteTicket(ticket); + const ReturnCode write_ret = WriteTicket(m_ios.GetFS().get(), ticket); if (write_ret != IPC_SUCCESS) return write_ret; @@ -343,8 +344,7 @@ static bool CheckIfContentHashMatches(const std::vector& content, const IOS: static std::string GetImportContentPath(u64 title_id, u32 content_id) { - return Common::GetImportTitlePath(title_id, Common::FROM_SESSION_ROOT) + - StringFromFormat("/content/%08x.app", content_id); + return Common::GetImportTitlePath(title_id) + StringFromFormat("/content/%08x.app", content_id); } ReturnCode ES::ImportContentEnd(Context& context, u32 content_fd) @@ -371,38 +371,39 @@ ReturnCode ES::ImportContentEnd(Context& context, u32 content_fd) return ES_HASH_MISMATCH; } + const auto fs = m_ios.GetFS(); std::string content_path; if (content_info.IsShared()) { - IOS::ES::SharedContentMap shared_content{m_ios.GetFS()}; - content_path = Common::RootUserPath(Common::FROM_SESSION_ROOT) + - shared_content.AddSharedContent(content_info.sha1); + IOS::ES::SharedContentMap shared_content{fs}; + content_path = shared_content.AddSharedContent(content_info.sha1); } else { content_path = GetImportContentPath(context.title_import_export.tmd.GetTitleId(), context.title_import_export.content.id); } - File::CreateFullPath(content_path); const std::string temp_path = - Common::RootUserPath(Common::FROM_SESSION_ROOT) + - StringFromFormat("/tmp/%08x.app", context.title_import_export.content.id); - File::CreateFullPath(temp_path); + "/tmp/" + content_path.substr(content_path.find_last_of('/') + 1, std::string::npos); + fs->CreateFile(PID_KERNEL, PID_KERNEL, temp_path, 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, + FS::Mode::None); { - File::IOFile file(temp_path, "wb"); - if (!file.WriteBytes(decrypted_data.data(), content_info.size)) + const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, temp_path, FS::Mode::Write); + if (!file || !file->Write(decrypted_data.data(), content_info.size)) { ERROR_LOG(IOS_ES, "ImportContentEnd: Failed to write to %s", temp_path.c_str()); return ES_EIO; } } - if (!File::Rename(temp_path, content_path)) + const FS::ResultCode rename_result = fs->Rename(PID_KERNEL, PID_KERNEL, temp_path, content_path); + if (rename_result != FS::ResultCode::Success) { + fs->Delete(PID_KERNEL, PID_KERNEL, temp_path); ERROR_LOG(IOS_ES, "ImportContentEnd: Failed to move content to %s", content_path.c_str()); - return ES_EIO; + return FS::ConvertResult(rename_result); } context.title_import_export.content = {}; @@ -437,8 +438,9 @@ ReturnCode ES::ImportTitleDone(Context& context) // Note: the import hasn't been finalised yet, so the whole title directory // is still in /import, not /title. - return File::Exists(Common::GetImportTitlePath(title_id, Common::FROM_SESSION_ROOT) + - StringFromFormat("/content/%08x.app", content.id)); + const std::string path = Common::GetImportTitlePath(title_id) + + StringFromFormat("/content/%08x.app", content.id); + return m_ios.GetFS()->GetMetadata(PID_KERNEL, PID_KERNEL, path).Succeeded(); }); if (!has_all_required_contents) return ES_EINVAL; @@ -499,17 +501,8 @@ ReturnCode ES::DeleteTitle(u64 title_id) if (!CanDeleteTitle(title_id)) return ES_EINVAL; - const std::string title_dir = Common::GetTitlePath(title_id, Common::FROM_SESSION_ROOT); - if (!File::IsDirectory(title_dir)) - return FS_ENOENT; - - if (!File::DeleteDirRecursively(title_dir)) - { - ERROR_LOG(IOS_ES, "DeleteTitle: Failed to delete title directory: %s", title_dir.c_str()); - return FS_EACCESS; - } - - return IPC_SUCCESS; + const std::string title_dir = Common::GetTitlePath(title_id); + return FS::ConvertResult(m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, title_dir)); } IPCCommandResult ES::DeleteTitle(const IOCtlVRequest& request) @@ -523,6 +516,7 @@ IPCCommandResult ES::DeleteTitle(const IOCtlVRequest& request) ReturnCode ES::DeleteTicket(const u8* ticket_view) { + const auto fs = m_ios.GetFS(); const u64 title_id = Common::swap64(ticket_view + offsetof(IOS::ES::TicketView, title_id)); if (!CanDeleteTitle(title_id)) @@ -536,24 +530,26 @@ ReturnCode ES::DeleteTicket(const u8* ticket_view) ticket.DeleteTicket(ticket_id); const std::vector& new_ticket = ticket.GetBytes(); - const std::string ticket_path = Common::GetTicketFileName(title_id, Common::FROM_SESSION_ROOT); + const std::string ticket_path = Common::GetTicketFileName(title_id); + if (!new_ticket.empty()) { - File::IOFile ticket_file(ticket_path, "wb"); - if (!ticket_file || !ticket_file.WriteBytes(new_ticket.data(), new_ticket.size())) + const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, ticket_path, FS::Mode::ReadWrite); + if (!file || !file->Write(new_ticket.data(), new_ticket.size())) return ES_EIO; } - - // Delete the ticket file if it is now empty. - if (new_ticket.empty()) - File::Delete(ticket_path); + else + { + // Delete the ticket file if it is now empty. + fs->Delete(PID_KERNEL, PID_KERNEL, ticket_path); + } // Delete the ticket directory if it is now empty. const std::string ticket_parent_dir = - Common::RootUserPath(Common::FROM_CONFIGURED_ROOT) + StringFromFormat("/ticket/%08x", static_cast(title_id >> 32)); - const auto ticket_parent_dir_entries = File::ScanDirectoryTree(ticket_parent_dir, false); - if (ticket_parent_dir_entries.children.empty()) - File::DeleteDir(ticket_parent_dir); + const auto ticket_parent_dir_entries = + fs->ReadDirectory(PID_KERNEL, PID_KERNEL, ticket_parent_dir); + if (ticket_parent_dir_entries && ticket_parent_dir_entries->empty()) + fs->Delete(PID_KERNEL, PID_KERNEL, ticket_parent_dir); return IPC_SUCCESS; } @@ -573,14 +569,15 @@ ReturnCode ES::DeleteTitleContent(u64 title_id) const if (!CanDeleteTitle(title_id)) return ES_EINVAL; - const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT); - if (!File::IsDirectory(content_dir)) - return FS_ENOENT; + const std::string content_dir = Common::GetTitleContentPath(title_id); + const auto files = m_ios.GetFS()->ReadDirectory(PID_KERNEL, PID_KERNEL, content_dir); + if (!files) + return FS::ConvertResult(files.Error()); - for (const auto& file : File::ScanDirectoryTree(content_dir, false).children) + for (const std::string& file_name : *files) { - if (file.virtualName.size() == 12 && file.virtualName.compare(8, 4, ".app") == 0) - File::Delete(file.physicalName); + if (file_name.size() == 12 && file_name.compare(8, 4, ".app") == 0) + m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, content_dir + '/' + file_name); } return IPC_SUCCESS; @@ -606,13 +603,9 @@ ReturnCode ES::DeleteContent(u64 title_id, u32 content_id) const if (!tmd.FindContentById(content_id, &content)) return ES_EINVAL; - if (!File::Delete(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT) + - StringFromFormat("/%08x.app", content_id))) - { - return FS_ENOENT; - } - - return IPC_SUCCESS; + return FS::ConvertResult(m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, + Common::GetTitleContentPath(title_id) + + StringFromFormat("/%08x.app", content_id))); } IPCCommandResult ES::DeleteContent(const IOCtlVRequest& request) @@ -812,7 +805,7 @@ ReturnCode ES::DeleteSharedContent(const std::array& sha1) const return ES_EINVAL; // Delete the shared content and update the content map. - const auto delete_result = m_ios.GetFS()->Delete(0, 0, *content_path); + const auto delete_result = m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, *content_path); if (delete_result != FS::ResultCode::Success) return FS::ConvertResult(delete_result);