mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +00:00
ncm: refactor rights cache
This commit is contained in:
parent
f93a1a987c
commit
9b34fc7ce7
12 changed files with 276 additions and 195 deletions
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
union RightsId {
|
||||
u8 data[0x10];
|
||||
u64 data64[2];
|
||||
};
|
||||
static_assert(sizeof(RightsId) == 0x10);
|
||||
static_assert(std::is_pod<RightsId>::value);
|
||||
|
||||
/* Rights ID API */
|
||||
Result GetRightsId(RightsId *out, const char *path);
|
||||
Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path);
|
||||
|
||||
}
|
|
@ -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<PlaceHolderId> 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<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id) = 0;
|
||||
virtual Result GetRightsIdFromContentId(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, ContentId content_id) = 0;
|
||||
virtual Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id) = 0;
|
||||
virtual Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id) = 0;
|
||||
virtual Result WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) = 0;
|
||||
virtual Result GetFreeSpaceSize(sf::Out<u64> out_size) = 0;
|
||||
virtual Result GetTotalSpaceSize(sf::Out<u64> out_size) = 0;
|
||||
virtual Result FlushPlaceHolder() = 0;
|
||||
virtual Result GetSizeFromPlaceHolderId(sf::Out<u64> out, PlaceHolderId placeholder_id) = 0;
|
||||
virtual Result RepairInvalidFileAttribute() = 0;
|
||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) = 0;
|
||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) = 0;
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(GeneratePlaceHolderId),
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/fs/fs_rights_id.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
|
@ -542,6 +543,14 @@ namespace ams::ncm {
|
|||
static_assert(sizeof(ProgramLocation) == 0x10 && std::is_pod<ProgramLocation>::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<RightsId>::value);
|
||||
|
||||
struct ContentMetaKey {
|
||||
ProgramId id;
|
||||
u32 version;
|
||||
|
|
31
libraries/libstratosphere/source/fs/fs_rights_id.cpp
Normal file
31
libraries/libstratosphere/source/fs/fs_rights_id.cpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include <stratosphere/fs/fs_rights_id.hpp>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
|
@ -20,10 +20,10 @@
|
|||
#include <optional>
|
||||
|
||||
#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<ReadOnlyContentStorageInterface>();
|
||||
auto content_storage = std::make_shared<ReadOnlyContentStorageImpl>();
|
||||
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<ContentStorageInterface>();
|
||||
auto content_storage = std::make_shared<ContentStorageImpl>();
|
||||
|
||||
switch (storage_id) {
|
||||
case StorageId::BuiltInSystem:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,18 +14,18 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<MakeContentPathFunc>(path::MakeContentPathFlat)) {
|
||||
return 1;
|
||||
} else if (this->make_content_path_func == static_cast<MakeContentPathFunc>(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<PlaceHolderId> out) {
|
||||
Result ContentStorageImpl::GeneratePlaceHolderId(sf::Out<PlaceHolderId> 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<bool> out, PlaceHolderId placeholder_id) {
|
||||
Result ContentStorageImpl::HasPlaceHolder(sf::Out<bool> 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<s64>::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<bool> out, ContentId content_id) {
|
||||
Result ContentStorageImpl::Has(sf::Out<bool> 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<lr::Path> out, ContentId content_id) {
|
||||
Result ContentStorageImpl::GetPath(sf::Out<lr::Path> 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<lr::Path> out, PlaceHolderId placeholder_id) {
|
||||
Result ContentStorageImpl::GetPlaceHolderPath(sf::Out<lr::Path> 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<u32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) {
|
||||
Result ContentStorageImpl::ListPlaceHolder(sf::Out<u32> out_count, const sf::OutArray<PlaceHolderId> &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<u32> out_count) {
|
||||
Result ContentStorageImpl::GetContentCount(sf::Out<u32> 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<u32> out_count, const sf::OutArray<ContentId> &out_buf, u32 start_offset) {
|
||||
Result ContentStorageImpl::ListContentId(sf::Out<u32> out_count, const sf::OutArray<ContentId> &out_buf, u32 start_offset) {
|
||||
R_UNLESS(start_offset <= std::numeric_limits<s32>::max(), ncm::ResultInvalidOffset());
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
|
@ -308,7 +308,7 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentStorageInterface::GetSizeFromContentId(sf::Out<u64> out_size, ContentId content_id) {
|
||||
Result ContentStorageImpl::GetSizeFromContentId(sf::Out<u64> 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<s64>::max(), ncm::ResultInvalidOffset());
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
@ -370,82 +370,43 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id) {
|
||||
Result ContentStorageImpl::GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> 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<u64>(key_generation));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentStorageInterface::GetRightsIdFromContentId(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, ContentId content_id) {
|
||||
Result ContentStorageImpl::GetRightsIdFromContentId(sf::Out<ncm::RightsId> 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<s64>::max(), ncm::ResultInvalidOffset());
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
@ -472,26 +433,26 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentStorageInterface::GetFreeSpaceSize(sf::Out<u64> out_size) {
|
||||
Result ContentStorageImpl::GetFreeSpaceSize(sf::Out<u64> 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<u64> out_size) {
|
||||
Result ContentStorageImpl::GetTotalSpaceSize(sf::Out<u64> 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<u64> out_size, PlaceHolderId placeholder_id) {
|
||||
Result ContentStorageImpl::GetSizeFromPlaceHolderId(sf::Out<u64> 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<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) {
|
||||
Result ContentStorageImpl::GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> 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();
|
||||
}
|
|
@ -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<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id) override;
|
||||
virtual Result GetRightsIdFromContentId(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, ContentId content_id) override;
|
||||
virtual Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id) override;
|
||||
virtual Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id) override;
|
||||
virtual Result WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) override;
|
||||
virtual Result GetFreeSpaceSize(sf::Out<u64> out_size) override;
|
||||
virtual Result GetTotalSpaceSize(sf::Out<u64> out_size) override;
|
||||
virtual Result FlushPlaceHolder() override;
|
||||
virtual Result GetSizeFromPlaceHolderId(sf::Out<u64> out, PlaceHolderId placeholder_id) override;
|
||||
virtual Result RepairInvalidFileAttribute() override;
|
||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) override;
|
||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) override;
|
||||
};
|
||||
|
||||
}
|
48
stratosphere/ncm/source/ncm_content_storage_impl_base.hpp
Normal file
48
stratosphere/ncm/source/ncm_content_storage_impl_base.hpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<PlaceHolderId> out) {
|
||||
Result ReadOnlyContentStorageImpl::GeneratePlaceHolderId(sf::Out<PlaceHolderId> 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<bool> out, PlaceHolderId placeholder_id) {
|
||||
Result ReadOnlyContentStorageImpl::HasPlaceHolder(sf::Out<bool> 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<bool> out, ContentId content_id) {
|
||||
Result ReadOnlyContentStorageImpl::Has(sf::Out<bool> 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<lr::Path> out, ContentId content_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetPath(sf::Out<lr::Path> 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<lr::Path> out, PlaceHolderId placeholder_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetPlaceHolderPath(sf::Out<lr::Path> out, PlaceHolderId placeholder_id) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() {
|
||||
Result ReadOnlyContentStorageImpl::CleanupAllPlaceHolder() {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::ListPlaceHolder(sf::Out<u32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) {
|
||||
Result ReadOnlyContentStorageImpl::ListPlaceHolder(sf::Out<u32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::GetContentCount(sf::Out<u32> out_count) {
|
||||
Result ReadOnlyContentStorageImpl::GetContentCount(sf::Out<u32> out_count) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::ListContentId(sf::Out<u32> out_count, const sf::OutArray<ContentId> &out_buf, u32 start_offset) {
|
||||
Result ReadOnlyContentStorageImpl::ListContentId(sf::Out<u32> out_count, const sf::OutArray<ContentId> &out_buf, u32 start_offset) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::GetSizeFromContentId(sf::Out<u64> out_size, ContentId content_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetSizeFromContentId(sf::Out<u64> 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<s64>::max(), ncm::ResultInvalidOffset());
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
@ -174,16 +174,13 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, ContentId content_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetRightsIdFromContentId(sf::Out<ncm::RightsId> 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<u64>(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<u64> out_size) {
|
||||
Result ReadOnlyContentStorageImpl::GetFreeSpaceSize(sf::Out<u64> out_size) {
|
||||
out_size.SetValue(0);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(sf::Out<u64> out_size) {
|
||||
Result ReadOnlyContentStorageImpl::GetTotalSpaceSize(sf::Out<u64> out_size) {
|
||||
out_size.SetValue(0);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::FlushPlaceHolder() {
|
||||
Result ReadOnlyContentStorageImpl::FlushPlaceHolder() {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(sf::Out<u64> out, PlaceHolderId placeholder_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetSizeFromPlaceHolderId(sf::Out<u64> out, PlaceHolderId placeholder_id) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() {
|
||||
Result ReadOnlyContentStorageImpl::RepairInvalidFileAttribute() {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
|
@ -17,10 +17,11 @@
|
|||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
#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<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id) override;
|
||||
virtual Result GetRightsIdFromContentId(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, ContentId content_id) override;
|
||||
virtual Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id) override;
|
||||
virtual Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id) override;
|
||||
virtual Result WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) override;
|
||||
virtual Result GetFreeSpaceSize(sf::Out<u64> out_size) override;
|
||||
virtual Result GetTotalSpaceSize(sf::Out<u64> out_size) override;
|
||||
virtual Result FlushPlaceHolder() override;
|
||||
virtual Result GetSizeFromPlaceHolderId(sf::Out<u64> out, PlaceHolderId placeholder_id) override;
|
||||
virtual Result RepairInvalidFileAttribute() override;
|
||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<FsRightsId> out_rights_id, sf::Out<u64> out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) override;
|
||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) override;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue