From 9b34fc7ce7f715fbe57d3c2f3b093a60f914952b Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 29 Feb 2020 22:21:55 +1100 Subject: [PATCH] ncm: refactor rights cache --- .../include/stratosphere/fs/fs_rights_id.hpp | 32 ++++ .../ncm/ncm_i_content_storage.hpp | 19 +- .../include/stratosphere/ncm/ncm_types.hpp | 9 + .../source/fs/fs_rights_id.cpp | 31 +++ .../ncm/source/impl/ncm_content_manager.cpp | 8 +- .../ncm/source/impl/ncm_rights_cache.hpp | 52 ++++- ...orage.cpp => ncm_content_storage_impl.cpp} | 179 ++++++------------ ...orage.hpp => ncm_content_storage_impl.hpp} | 11 +- .../source/ncm_content_storage_impl_base.hpp | 48 +++++ stratosphere/ncm/source/ncm_fs.cpp | 4 +- ...=> ncm_read_only_content_storage_impl.cpp} | 69 ++++--- ...=> ncm_read_only_content_storage_impl.hpp} | 9 +- 12 files changed, 276 insertions(+), 195 deletions(-) create mode 100644 libraries/libstratosphere/include/stratosphere/fs/fs_rights_id.hpp create mode 100644 libraries/libstratosphere/source/fs/fs_rights_id.cpp rename stratosphere/ncm/source/{ncm_content_storage.cpp => ncm_content_storage_impl.cpp} (67%) rename stratosphere/ncm/source/{ncm_content_storage.hpp => ncm_content_storage_impl.hpp} (90%) create mode 100644 stratosphere/ncm/source/ncm_content_storage_impl_base.hpp rename stratosphere/ncm/source/{ncm_read_only_content_storage.cpp => ncm_read_only_content_storage_impl.cpp} (62%) rename stratosphere/ncm/source/{ncm_read_only_content_storage.hpp => ncm_read_only_content_storage_impl.hpp} (87%) diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_rights_id.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_rights_id.hpp new file mode 100644 index 000000000..6c81d83bb --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_rights_id.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::fs { + + union RightsId { + u8 data[0x10]; + u64 data64[2]; + }; + static_assert(sizeof(RightsId) == 0x10); + static_assert(std::is_pod::value); + + /* Rights ID API */ + Result GetRightsId(RightsId *out, const char *path); + Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path); + +} \ No newline at end of file diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp index 51361e2cb..f40c9a55b 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp @@ -22,6 +22,8 @@ namespace ams::ncm { class IContentStorage : public sf::IServiceObject { + NON_COPYABLE(IContentStorage); + NON_MOVEABLE(IContentStorage); protected: enum class CommandId { GeneratePlaceHolderId = 0, @@ -53,15 +55,8 @@ namespace ams::ncm { RepairInvalidFileAttribute = 26, GetRightsIdFromPlaceHolderIdWithCache = 27, }; - protected: - char root_path[FS_MAX_PATH-1]; - MakeContentPathFunc make_content_path_func; - bool disabled; - protected: - Result EnsureEnabled() { - R_UNLESS(!this->disabled, ncm::ResultInvalidContentStorage()); - return ResultSuccess(); - } + public: + IContentStorage() { /* ... */ } public: virtual Result GeneratePlaceHolderId(sf::Out out) = 0; virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) = 0; @@ -82,15 +77,15 @@ namespace ams::ncm { virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) = 0; virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) = 0; virtual Result ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) = 0; - virtual Result GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id) = 0; - virtual Result GetRightsIdFromContentId(sf::Out out_rights_id, sf::Out out_key_generation, ContentId content_id) = 0; + virtual Result GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, PlaceHolderId placeholder_id) = 0; + virtual Result GetRightsIdFromContentId(sf::Out out_rights_id, ContentId content_id) = 0; virtual Result WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) = 0; virtual Result GetFreeSpaceSize(sf::Out out_size) = 0; virtual Result GetTotalSpaceSize(sf::Out out_size) = 0; virtual Result FlushPlaceHolder() = 0; virtual Result GetSizeFromPlaceHolderId(sf::Out out, PlaceHolderId placeholder_id) = 0; virtual Result RepairInvalidFileAttribute() = 0; - virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) = 0; + virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) = 0; public: DEFINE_SERVICE_DISPATCH_TABLE { MAKE_SERVICE_COMMAND_META(GeneratePlaceHolderId), diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp index c47a037d3..d370c40dd 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp @@ -16,6 +16,7 @@ #pragma once #include +#include namespace ams::ncm { @@ -542,6 +543,14 @@ namespace ams::ncm { static_assert(sizeof(ProgramLocation) == 0x10 && std::is_pod::value, "ProgramLocation definition!"); static_assert(sizeof(ProgramLocation) == sizeof(::NcmProgramLocation) && alignof(ProgramLocation) == alignof(::NcmProgramLocation), "ProgramLocation Libnx Compatibility"); + struct RightsId { + fs::RightsId id; + u8 key_generation; + u8 reserved[7]; + }; + static_assert(sizeof(RightsId) == 0x18); + static_assert(std::is_pod::value); + struct ContentMetaKey { ProgramId id; u32 version; diff --git a/libraries/libstratosphere/source/fs/fs_rights_id.cpp b/libraries/libstratosphere/source/fs/fs_rights_id.cpp new file mode 100644 index 000000000..a0f6d6cd8 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fs_rights_id.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include + +namespace ams::fs { + + Result GetRightsId(RightsId *out, const char *path) { + static_assert(sizeof(RightsId) == sizeof(::FsRightsId)); + return fsGetRightsIdByPath(path, reinterpret_cast<::FsRightsId *>(out)); + } + + Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path) { + static_assert(sizeof(RightsId) == sizeof(::FsRightsId)); + return fsGetRightsIdAndKeyGenerationByPath(path, out_key_generation, reinterpret_cast<::FsRightsId *>(out)); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 084e9c8f9..57491163c 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -20,10 +20,10 @@ #include #include "../ncm_content_meta_database.hpp" -#include "../ncm_content_storage.hpp" +#include "../ncm_content_storage_impl.hpp" #include "../ncm_fs.hpp" #include "../ncm_make_path.hpp" -#include "../ncm_read_only_content_storage.hpp" +#include "../ncm_read_only_content_storage_impl.hpp" #include "ncm_content_manager.hpp" #include "ncm_rights_cache.hpp" @@ -427,14 +427,14 @@ namespace ams::ncm::impl { auto mount_guard = SCOPE_GUARD { fs::Unmount(root->mount_point); }; if (storage_id == StorageId::GameCard) { - auto content_storage = std::make_shared(); + auto content_storage = std::make_shared(); R_TRY(content_storage->Initialize(root->path, path::MakeContentPathFlat)); root->content_storage = std::move(content_storage); } else { MakeContentPathFunc content_path_func = nullptr; MakePlaceHolderPathFunc placeholder_path_func = nullptr; bool delay_flush = false; - auto content_storage = std::make_shared(); + auto content_storage = std::make_shared(); switch (storage_id) { case StorageId::BuiltInSystem: diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp index 80808c1e0..3dc8baf5a 100644 --- a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp +++ b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp @@ -21,21 +21,22 @@ namespace ams::ncm::impl { class RightsIdCache { - public: + NON_COPYABLE(RightsIdCache); + NON_MOVEABLE(RightsIdCache); + private: static constexpr size_t MaxEntries = 0x80; - public: + private: struct Entry { public: util::Uuid uuid; - FsRightsId rights_id; - u64 key_generation; + ncm::RightsId rights_id; u64 last_accessed; }; - + private: Entry entries[MaxEntries]; u64 counter; os::Mutex mutex; - + public: RightsIdCache() { this->Invalidate(); } @@ -46,6 +47,45 @@ namespace ams::ncm::impl { this->entries[i].last_accessed = 1; } } + + void Store(ContentId content_id, ncm::RightsId rights_id) { + std::scoped_lock lk(this->mutex); + Entry *eviction_candidate = &this->entries[0]; + + /* Find a suitable existing entry to store our new one at. */ + for (size_t i = 1; i < MaxEntries; i++) { + Entry *entry = &this->entries[i]; + + /* Change eviction candidates if the uuid already matches ours, or if the uuid doesn't already match and the last_accessed count is lower */ + if (content_id == entry->uuid || (content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) { + eviction_candidate = entry; + } + } + + /* Update the cache. */ + eviction_candidate->uuid = content_id.uuid; + eviction_candidate->rights_id = rights_id; + eviction_candidate->last_accessed = this->counter; + this->counter++; + } + + bool Find(ncm::RightsId *out_rights_id, ContentId content_id) { + std::scoped_lock lk(this->mutex); + + /* Attempt to locate the content id in the cache. */ + for (size_t i = 0; i < MaxEntries; i++) { + Entry *entry = &this->entries[i]; + + if (entry->last_accessed != 1 && content_id == entry->uuid) { + entry->last_accessed = this->counter; + this->counter++; + *out_rights_id = entry->rights_id; + return true; + } + } + + return false; + } }; } diff --git a/stratosphere/ncm/source/ncm_content_storage.cpp b/stratosphere/ncm/source/ncm_content_storage_impl.cpp similarity index 67% rename from stratosphere/ncm/source/ncm_content_storage.cpp rename to stratosphere/ncm/source/ncm_content_storage_impl.cpp index 16aacf6f2..30bbe9e6e 100644 --- a/stratosphere/ncm/source/ncm_content_storage.cpp +++ b/stratosphere/ncm/source/ncm_content_storage_impl.cpp @@ -14,18 +14,18 @@ * along with this program. If not, see . */ -#include "ncm_content_storage.hpp" +#include "ncm_content_storage_impl.hpp" #include "ncm_fs.hpp" #include "ncm_make_path.hpp" #include "ncm_utils.hpp" namespace ams::ncm { - ContentStorageInterface::~ContentStorageInterface() { + ContentStorageImpl::~ContentStorageImpl() { this->Finalize(); } - Result ContentStorageInterface::Initialize(const char *root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush, impl::RightsIdCache *rights_id_cache) { + Result ContentStorageImpl::Initialize(const char *root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush, impl::RightsIdCache *rights_id_cache) { R_TRY(this->EnsureEnabled()); R_TRY(fs::CheckContentStorageDirectoriesExist(root_path)); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); @@ -39,19 +39,19 @@ namespace ams::ncm { return ResultSuccess(); } - void ContentStorageInterface::Finalize() { + void ContentStorageImpl::Finalize() { this->ClearContentCache(); this->placeholder_accessor.InvalidateAll(); } - void ContentStorageInterface::ClearContentCache() { + void ContentStorageImpl::ClearContentCache() { if (this->cached_content_id != InvalidContentId) { fclose(this->content_cache_file_handle); this->cached_content_id = InvalidContentId; } } - unsigned int ContentStorageInterface::GetContentDirectoryDepth() { + unsigned int ContentStorageImpl::GetContentDirectoryDepth() { if (this->make_content_path_func == static_cast(path::MakeContentPathFlat)) { return 1; } else if (this->make_content_path_func == static_cast(path::MakeContentPathHashByteLayered)) { @@ -65,7 +65,7 @@ namespace ams::ncm { AMS_ABORT(); } - Result ContentStorageInterface::OpenCachedContentFile(ContentId content_id) { + Result ContentStorageImpl::OpenCachedContentFile(ContentId content_id) { R_UNLESS(this->cached_content_id != content_id, ResultSuccess()); this->ClearContentCache(); @@ -80,13 +80,13 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GeneratePlaceHolderId(sf::Out out) { + Result ContentStorageImpl::GeneratePlaceHolderId(sf::Out out) { R_TRY(this->EnsureEnabled()); out.SetValue({util::GenerateUuid()}); return ResultSuccess(); } - Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + Result ContentStorageImpl::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -98,12 +98,12 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + Result ContentStorageImpl::DeletePlaceHolder(PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); return this->placeholder_accessor.Delete(placeholder_id); } - Result ContentStorageInterface::HasPlaceHolder(sf::Out out, PlaceHolderId placeholder_id) { + Result ContentStorageImpl::HasPlaceHolder(sf::Out out, PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -116,7 +116,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, sf::InBuffer data) { + Result ContentStorageImpl::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, sf::InBuffer data) { /* Offset is too large */ R_UNLESS(offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); @@ -124,7 +124,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + Result ContentStorageImpl::Register(PlaceHolderId placeholder_id, ContentId content_id) { this->ClearContentCache(); R_TRY(this->EnsureEnabled()); @@ -144,7 +144,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::Delete(ContentId content_id) { + Result ContentStorageImpl::Delete(ContentId content_id) { R_TRY(this->EnsureEnabled()); this->ClearContentCache(); @@ -160,7 +160,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::Has(sf::Out out, ContentId content_id) { + Result ContentStorageImpl::Has(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -173,7 +173,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GetPath(sf::Out out, ContentId content_id) { + Result ContentStorageImpl::GetPath(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -184,7 +184,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GetPlaceHolderPath(sf::Out out, PlaceHolderId placeholder_id) { + Result ContentStorageImpl::GetPlaceHolderPath(sf::Out out, PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -195,7 +195,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::CleanupAllPlaceHolder() { + Result ContentStorageImpl::CleanupAllPlaceHolder() { R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -209,7 +209,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::ListPlaceHolder(sf::Out out_count, const sf::OutArray &out_buf) { + Result ContentStorageImpl::ListPlaceHolder(sf::Out out_count, const sf::OutArray &out_buf) { R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -236,7 +236,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GetContentCount(sf::Out out_count) { + Result ContentStorageImpl::GetContentCount(sf::Out out_count) { R_TRY(this->EnsureEnabled()); char content_root_path[FS_MAX_PATH] = {0}; @@ -259,7 +259,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::ListContentId(sf::Out out_count, const sf::OutArray &out_buf, u32 start_offset) { + Result ContentStorageImpl::ListContentId(sf::Out out_count, const sf::OutArray &out_buf, u32 start_offset) { R_UNLESS(start_offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); @@ -308,7 +308,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GetSizeFromContentId(sf::Out out_size, ContentId content_id) { + Result ContentStorageImpl::GetSizeFromContentId(sf::Out out_size, ContentId content_id) { R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -320,14 +320,14 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::DisableForcibly() { + Result ContentStorageImpl::DisableForcibly() { this->disabled = true; this->ClearContentCache(); this->placeholder_accessor.InvalidateAll(); return ResultSuccess(); } - Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + Result ContentStorageImpl::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { R_TRY(this->EnsureEnabled()); char old_content_path[FS_MAX_PATH] = {0}; @@ -352,13 +352,13 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + Result ContentStorageImpl::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { R_TRY(this->EnsureEnabled()); R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess(); } - Result ContentStorageInterface::ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) { + Result ContentStorageImpl::ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) { /* Offset is too large */ R_UNLESS(offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); @@ -370,82 +370,43 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id) { + Result ContentStorageImpl::GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); - FsRightsId rights_id = {0}; - u8 key_generation = 0; - char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); - R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); + ncm::RightsId rights_id; + R_TRY(GetRightsId(&rights_id, common_path)); out_rights_id.SetValue(rights_id); - out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess(); } - Result ContentStorageInterface::GetRightsIdFromContentId(sf::Out out_rights_id, sf::Out out_key_generation, ContentId content_id) { + Result ContentStorageImpl::GetRightsIdFromContentId(sf::Out out_rights_id, ContentId content_id) { R_TRY(this->EnsureEnabled()); - { - std::scoped_lock lk(this->rights_id_cache->mutex); - - /* Attempt to locate the content id in the cache. */ - for (size_t i = 0; i < impl::RightsIdCache::MaxEntries; i++) { - impl::RightsIdCache::Entry *entry = &this->rights_id_cache->entries[i]; - - if (entry->last_accessed != 1 && content_id == entry->uuid) { - entry->last_accessed = this->rights_id_cache->counter; - this->rights_id_cache->counter++; - out_rights_id.SetValue(entry->rights_id); - out_key_generation.SetValue(entry->key_generation); - return ResultSuccess(); - } - } + if (this->rights_id_cache->Find(out_rights_id.GetPointer(), content_id)) { + return ResultSuccess(); } - FsRightsId rights_id = {0}; - u8 key_generation = 0; char content_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); - R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); - { - std::scoped_lock lk(this->rights_id_cache->mutex); - impl::RightsIdCache::Entry *eviction_candidate = &this->rights_id_cache->entries[0]; - - /* Find a suitable existing entry to store our new one at. */ - for (size_t i = 1; i < impl::RightsIdCache::MaxEntries; i++) { - impl::RightsIdCache::Entry *entry = &this->rights_id_cache->entries[i]; - - /* Change eviction candidates if the uuid already matches ours, or if the uuid doesn't already match and the last_accessed count is lower */ - if (content_id == entry->uuid || (content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) { - eviction_candidate = entry; - } - } - - /* Update the cache. */ - eviction_candidate->uuid = content_id.uuid; - eviction_candidate->rights_id = rights_id; - eviction_candidate->key_generation = key_generation; - eviction_candidate->last_accessed = this->rights_id_cache->counter; - this->rights_id_cache->counter++; - - /* Set output. */ - out_rights_id.SetValue(rights_id); - out_key_generation.SetValue(key_generation); - } + ncm::RightsId rights_id; + R_TRY(GetRightsId(&rights_id, common_path)); + this->rights_id_cache->Store(content_id, rights_id); + /* Set output. */ + out_rights_id.SetValue(rights_id); return ResultSuccess(); } - Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) { + Result ContentStorageImpl::WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) { /* Offset is too large */ R_UNLESS(offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); @@ -472,26 +433,26 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GetFreeSpaceSize(sf::Out out_size) { + Result ContentStorageImpl::GetFreeSpaceSize(sf::Out out_size) { struct statvfs st = {0}; R_UNLESS(statvfs(this->root_path, &st) != -1, fsdevGetLastResult()); out_size.SetValue(st.f_bfree); return ResultSuccess(); } - Result ContentStorageInterface::GetTotalSpaceSize(sf::Out out_size) { + Result ContentStorageImpl::GetTotalSpaceSize(sf::Out out_size) { struct statvfs st = {0}; R_UNLESS(statvfs(this->root_path, &st) != -1, fsdevGetLastResult()); out_size.SetValue(st.f_blocks); return ResultSuccess(); } - Result ContentStorageInterface::FlushPlaceHolder() { + Result ContentStorageImpl::FlushPlaceHolder() { this->placeholder_accessor.InvalidateAll(); return ResultSuccess(); } - Result ContentStorageInterface::GetSizeFromPlaceHolderId(sf::Out out_size, PlaceHolderId placeholder_id) { + Result ContentStorageImpl::GetSizeFromPlaceHolderId(sf::Out out_size, PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); bool found_in_cache = false; @@ -514,7 +475,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::RepairInvalidFileAttribute() { + Result ContentStorageImpl::RepairInvalidFileAttribute() { char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); unsigned int dir_depth = this->GetContentDirectoryDepth(); @@ -545,59 +506,25 @@ namespace ams::ncm { return ResultSuccess(); } - Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + Result ContentStorageImpl::GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) { R_TRY(this->EnsureEnabled()); - { - std::scoped_lock lk(this->rights_id_cache->mutex); - - /* Attempt to locate the content id in the cache. */ - for (size_t i = 0; i < impl::RightsIdCache::MaxEntries; i++) { - impl::RightsIdCache::Entry *entry = &this->rights_id_cache->entries[i]; - - if (entry->last_accessed != 1 && cache_content_id == entry->uuid) { - entry->last_accessed = this->rights_id_cache->counter; - this->rights_id_cache->counter++; - out_rights_id.SetValue(entry->rights_id); - out_key_generation.SetValue(entry->key_generation); - return ResultSuccess(); - } - } + if (this->rights_id_cache->Find(out_rights_id.GetPointer(), cache_content_id)) { + return ResultSuccess(); } - FsRightsId rights_id = {0}; - u8 key_generation = 0; - char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; + char placeholder_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); - R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); - { - std::scoped_lock lk(this->rights_id_cache->mutex); - impl::RightsIdCache::Entry *eviction_candidate = &this->rights_id_cache->entries[0]; + ncm::RightsId rights_id; + R_TRY(GetRightsId(&rights_id, common_path)); + this->rights_id_cache->Store(cache_content_id, rights_id); - /* Find a suitable existing entry to store our new one at. */ - for (size_t i = 1; i < impl::RightsIdCache::MaxEntries; i++) { - impl::RightsIdCache::Entry *entry = &this->rights_id_cache->entries[i]; - - /* Change eviction candidates if the uuid already matches ours, or if the uuid doesn't already match and the last_accessed count is lower */ - if (cache_content_id == entry->uuid || (cache_content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) { - eviction_candidate = entry; - } - } - - /* Update the cache. */ - eviction_candidate->uuid = cache_content_id.uuid; - eviction_candidate->rights_id = rights_id; - eviction_candidate->key_generation = key_generation; - eviction_candidate->last_accessed = this->rights_id_cache->counter; - this->rights_id_cache->counter++; - - /* Set output. */ - out_rights_id.SetValue(rights_id); - out_key_generation.SetValue(key_generation); - } + /* Set output. */ + out_rights_id.SetValue(rights_id); return ResultSuccess(); } diff --git a/stratosphere/ncm/source/ncm_content_storage.hpp b/stratosphere/ncm/source/ncm_content_storage_impl.hpp similarity index 90% rename from stratosphere/ncm/source/ncm_content_storage.hpp rename to stratosphere/ncm/source/ncm_content_storage_impl.hpp index bfa7468e1..87c3fd1d5 100644 --- a/stratosphere/ncm/source/ncm_content_storage.hpp +++ b/stratosphere/ncm/source/ncm_content_storage_impl.hpp @@ -20,18 +20,19 @@ #include "impl/ncm_placeholder_accessor.hpp" #include "impl/ncm_rights_cache.hpp" +#include "ncm_content_storage_impl_base.hpp" #include "ncm_path_utils.hpp" namespace ams::ncm { - class ContentStorageInterface : public IContentStorage { + class ContentStorageImpl : public ContentStorageImplBase { protected: impl::PlaceHolderAccessor placeholder_accessor; ContentId cached_content_id; FILE *content_cache_file_handle; impl::RightsIdCache *rights_id_cache; public: - ~ContentStorageInterface(); + ~ContentStorageImpl(); Result Initialize(const char *root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush, impl::RightsIdCache *rights_id_cache); void Finalize(); @@ -70,15 +71,15 @@ namespace ams::ncm { virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) override; virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) override; virtual Result ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) override; - virtual Result GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id) override; - virtual Result GetRightsIdFromContentId(sf::Out out_rights_id, sf::Out out_key_generation, ContentId content_id) override; + virtual Result GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, PlaceHolderId placeholder_id) override; + virtual Result GetRightsIdFromContentId(sf::Out out_rights_id, ContentId content_id) override; virtual Result WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) override; virtual Result GetFreeSpaceSize(sf::Out out_size) override; virtual Result GetTotalSpaceSize(sf::Out out_size) override; virtual Result FlushPlaceHolder() override; virtual Result GetSizeFromPlaceHolderId(sf::Out out, PlaceHolderId placeholder_id) override; virtual Result RepairInvalidFileAttribute() override; - virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) override; + virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) override; }; } diff --git a/stratosphere/ncm/source/ncm_content_storage_impl_base.hpp b/stratosphere/ncm/source/ncm_content_storage_impl_base.hpp new file mode 100644 index 000000000..bd79b0577 --- /dev/null +++ b/stratosphere/ncm/source/ncm_content_storage_impl_base.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +namespace ams::ncm { + + class ContentStorageImplBase : public IContentStorage { + NON_COPYABLE(ContentStorageImplBase); + NON_MOVEABLE(ContentStorageImplBase); + protected: + char root_path[FS_MAX_PATH-1]; + MakeContentPathFunc make_content_path_func; + bool disabled; + protected: + ContentStorageImplBase() { /* ... */ } + protected: + Result EnsureEnabled() { + R_UNLESS(!this->disabled, ncm::ResultInvalidContentStorage()); + return ResultSuccess(); + } + + static Result GetRightsId(ncm::RightsId *out_rights_id, const char *path) { + if (hos::GetVersion() >= hos::Version_300) { + R_TRY(ams::fs::GetRightsId(std::addressof(out_rights_id->id), std::addressof(out_rights_id->key_generation), path)); + } else { + R_TRY(ams::fs::GetRightsId(std::addressof(out_rights_id->id), path)); + out_rights_id->key_generation = 0; + } + return ResultSuccess(); + } + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 2658ff3a0..c92994043 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -44,7 +44,7 @@ namespace ams::ncm::fs { return ResultSuccess(); } - Result WriteFile(FILE *f, size_t offset, const void *buffer, size_t size, u32 option) { + Result WriteFile(FILE *f, size_t offset, const void *buffer, size_t size, ams::fs::WriteOption option) { R_UNLESS(fseek(f, 0, SEEK_END) == 0, fsdevGetLastResult()); size_t existing_size = ftell(f); @@ -52,7 +52,7 @@ namespace ams::ncm::fs { R_UNLESS(fseek(f, offset, SEEK_SET) == 0, fsdevGetLastResult()); R_UNLESS(fwrite(buffer, 1, size, f) == size, fsdevGetLastResult()); - if (option & FsWriteOption_Flush) { + if (option.HasFlushFlag()) { fflush(f); } diff --git a/stratosphere/ncm/source/ncm_read_only_content_storage.cpp b/stratosphere/ncm/source/ncm_read_only_content_storage_impl.cpp similarity index 62% rename from stratosphere/ncm/source/ncm_read_only_content_storage.cpp rename to stratosphere/ncm/source/ncm_read_only_content_storage_impl.cpp index 21e5ec7cb..65dc08f3c 100644 --- a/stratosphere/ncm/source/ncm_read_only_content_storage.cpp +++ b/stratosphere/ncm/source/ncm_read_only_content_storage_impl.cpp @@ -16,11 +16,11 @@ #include "ncm_fs.hpp" #include "ncm_path_utils.hpp" -#include "ncm_read_only_content_storage.hpp" +#include "ncm_read_only_content_storage_impl.hpp" namespace ams::ncm { - Result ReadOnlyContentStorageInterface::Initialize(const char *root_path, MakeContentPathFunc content_path_func) { + Result ReadOnlyContentStorageImpl::Initialize(const char *root_path, MakeContentPathFunc content_path_func) { R_TRY(this->EnsureEnabled()); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); @@ -30,35 +30,35 @@ namespace ams::ncm { return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(sf::Out out) { + Result ReadOnlyContentStorageImpl::GeneratePlaceHolderId(sf::Out out) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + Result ReadOnlyContentStorageImpl::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + Result ReadOnlyContentStorageImpl::DeletePlaceHolder(PlaceHolderId placeholder_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::HasPlaceHolder(sf::Out out, PlaceHolderId placeholder_id) { + Result ReadOnlyContentStorageImpl::HasPlaceHolder(sf::Out out, PlaceHolderId placeholder_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, sf::InBuffer data) { + Result ReadOnlyContentStorageImpl::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, sf::InBuffer data) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + Result ReadOnlyContentStorageImpl::Register(PlaceHolderId placeholder_id, ContentId content_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { + Result ReadOnlyContentStorageImpl::Delete(ContentId content_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::Has(sf::Out out, ContentId content_id) { + Result ReadOnlyContentStorageImpl::Has(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -76,7 +76,7 @@ namespace ams::ncm { return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::GetPath(sf::Out out, ContentId content_id) { + Result ReadOnlyContentStorageImpl::GetPath(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -96,27 +96,27 @@ namespace ams::ncm { return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(sf::Out out, PlaceHolderId placeholder_id) { + Result ReadOnlyContentStorageImpl::GetPlaceHolderPath(sf::Out out, PlaceHolderId placeholder_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { + Result ReadOnlyContentStorageImpl::CleanupAllPlaceHolder() { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::ListPlaceHolder(sf::Out out_count, const sf::OutArray &out_buf) { + Result ReadOnlyContentStorageImpl::ListPlaceHolder(sf::Out out_count, const sf::OutArray &out_buf) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::GetContentCount(sf::Out out_count) { + Result ReadOnlyContentStorageImpl::GetContentCount(sf::Out out_count) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::ListContentId(sf::Out out_count, const sf::OutArray &out_buf, u32 start_offset) { + Result ReadOnlyContentStorageImpl::ListContentId(sf::Out out_count, const sf::OutArray &out_buf, u32 start_offset) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::GetSizeFromContentId(sf::Out out_size, ContentId content_id) { + Result ReadOnlyContentStorageImpl::GetSizeFromContentId(sf::Out out_size, ContentId content_id) { R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -135,20 +135,20 @@ namespace ams::ncm { return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::DisableForcibly() { + Result ReadOnlyContentStorageImpl::DisableForcibly() { this->disabled = true; return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + Result ReadOnlyContentStorageImpl::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + Result ReadOnlyContentStorageImpl::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) { + Result ReadOnlyContentStorageImpl::ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) { /* Offset is too large */ R_UNLESS(offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); @@ -174,16 +174,13 @@ namespace ams::ncm { return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id) { + Result ReadOnlyContentStorageImpl::GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, PlaceHolderId placeholder_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(sf::Out out_rights_id, sf::Out out_key_generation, ContentId content_id) { + Result ReadOnlyContentStorageImpl::GetRightsIdFromContentId(sf::Out out_rights_id, ContentId content_id) { R_TRY(this->EnsureEnabled()); - FsRightsId rights_id = {0}; - u8 key_generation = 0; - char content_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; bool is_content_meta_file = false; @@ -196,41 +193,41 @@ namespace ams::ncm { } R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); - R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); - + + ncm::RightsId rights_id; + R_TRY(GetRightsId(&rights_id, common_path)); out_rights_id.SetValue(rights_id); - out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) { + Result ReadOnlyContentStorageImpl::WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(sf::Out out_size) { + Result ReadOnlyContentStorageImpl::GetFreeSpaceSize(sf::Out out_size) { out_size.SetValue(0); return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(sf::Out out_size) { + Result ReadOnlyContentStorageImpl::GetTotalSpaceSize(sf::Out out_size) { out_size.SetValue(0); return ResultSuccess(); } - Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { + Result ReadOnlyContentStorageImpl::FlushPlaceHolder() { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(sf::Out out, PlaceHolderId placeholder_id) { + Result ReadOnlyContentStorageImpl::GetSizeFromPlaceHolderId(sf::Out out, PlaceHolderId placeholder_id) { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { + Result ReadOnlyContentStorageImpl::RepairInvalidFileAttribute() { return ResultInvalidContentStorageOperation(); } - Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + Result ReadOnlyContentStorageImpl::GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) { return ResultInvalidContentStorageOperation(); } diff --git a/stratosphere/ncm/source/ncm_read_only_content_storage.hpp b/stratosphere/ncm/source/ncm_read_only_content_storage_impl.hpp similarity index 87% rename from stratosphere/ncm/source/ncm_read_only_content_storage.hpp rename to stratosphere/ncm/source/ncm_read_only_content_storage_impl.hpp index 8881f85b3..13e812957 100644 --- a/stratosphere/ncm/source/ncm_read_only_content_storage.hpp +++ b/stratosphere/ncm/source/ncm_read_only_content_storage_impl.hpp @@ -17,10 +17,11 @@ #pragma once #include #include +#include "ncm_content_storage_impl_base.hpp" namespace ams::ncm { - class ReadOnlyContentStorageInterface : public IContentStorage { + class ReadOnlyContentStorageImpl : public ContentStorageImplBase { public: Result Initialize(const char *root_path, MakeContentPathFunc content_path_func); public: @@ -43,15 +44,15 @@ namespace ams::ncm { virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) override; virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) override; virtual Result ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) override; - virtual Result GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id) override; - virtual Result GetRightsIdFromContentId(sf::Out out_rights_id, sf::Out out_key_generation, ContentId content_id) override; + virtual Result GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, PlaceHolderId placeholder_id) override; + virtual Result GetRightsIdFromContentId(sf::Out out_rights_id, ContentId content_id) override; virtual Result WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) override; virtual Result GetFreeSpaceSize(sf::Out out_size) override; virtual Result GetTotalSpaceSize(sf::Out out_size) override; virtual Result FlushPlaceHolder() override; virtual Result GetSizeFromPlaceHolderId(sf::Out out, PlaceHolderId placeholder_id) override; virtual Result RepairInvalidFileAttribute() override; - virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, sf::Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) override; + virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) override; }; }