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;
};
}