mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +00:00
ncm: client-side api
This commit is contained in:
parent
d40d2006e9
commit
7576ab3ab0
27 changed files with 1241 additions and 126 deletions
|
@ -18,5 +18,6 @@
|
|||
|
||||
#include "ncm/ncm_types.hpp"
|
||||
#include "ncm/ncm_content_meta.hpp"
|
||||
#include "ncm/ncm_i_content_meta_database.hpp"
|
||||
#include "ncm/ncm_i_content_storage.hpp"
|
||||
#include "ncm/ncm_content_meta_database.hpp"
|
||||
#include "ncm/ncm_content_storage.hpp"
|
||||
#include "ncm/ncm_api.hpp"
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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/ncm/ncm_types.hpp>
|
||||
#include <stratosphere/ncm/ncm_content_meta_database.hpp>
|
||||
#include <stratosphere/ncm/ncm_content_storage.hpp>
|
||||
#include <stratosphere/ncm/ncm_i_content_manager.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
/* Management. */
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
void InitializeWithObject(std::shared_ptr<IContentManager> manager_object);
|
||||
|
||||
/* Service API. */
|
||||
Result CreateContentStorage(StorageId storage_id);
|
||||
Result CreateContentMetaDatabase(StorageId storage_id);
|
||||
|
||||
Result VerifyContentStorage(StorageId storage_id);
|
||||
Result VerifyContentMetaDatabase(StorageId storage_id);
|
||||
|
||||
Result OpenContentStorage(ContentStorage *out, StorageId storage_id);
|
||||
Result OpenContentMetaDatabase(ContentMetaDatabase *out, StorageId storage_id);
|
||||
|
||||
Result CleanupContentMetaDatabase(StorageId storage_id);
|
||||
|
||||
Result ActivateContentStorage(StorageId storage_id);
|
||||
Result InactivateContentStorage(StorageId storage_id);
|
||||
|
||||
Result ActivateContentMetaDatabase(StorageId storage_id);
|
||||
Result InactivateContentMetaDatabase(StorageId storage_id);
|
||||
|
||||
Result InvalidateRightsIdCache();
|
||||
|
||||
/* Deprecated API. */
|
||||
Result CloseContentStorageForcibly(StorageId storage_id);
|
||||
Result CloseContentMetaDatabaseForcibly(StorageId storage_id);
|
||||
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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/ncm/ncm_types.hpp>
|
||||
#include <stratosphere/ncm/ncm_i_content_meta_database.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
class ContentMetaDatabase {
|
||||
NON_COPYABLE(ContentMetaDatabase);
|
||||
public:
|
||||
struct ListCount {
|
||||
u32 written;
|
||||
u32 total;
|
||||
};
|
||||
private:
|
||||
std::shared_ptr<IContentMetaDatabase> interface;
|
||||
public:
|
||||
ContentMetaDatabase() { /* ... */ }
|
||||
explicit ContentMetaDatabase(std::shared_ptr<IContentMetaDatabase> intf) : interface(std::move(intf)) { /* ... */ }
|
||||
|
||||
ContentMetaDatabase(ContentMetaDatabase &&rhs) {
|
||||
this->interface = std::move(rhs.interface);
|
||||
}
|
||||
|
||||
ContentMetaDatabase &operator=(ContentMetaDatabase &&rhs) {
|
||||
ContentMetaDatabase(std::move(rhs)).Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Swap(ContentMetaDatabase &rhs) {
|
||||
std::swap(this->interface, rhs.interface);
|
||||
}
|
||||
public:
|
||||
Result Set(const ContentMetaKey &key, const void *buf, size_t size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->Set(key, sf::InBuffer(buf, size));
|
||||
}
|
||||
|
||||
Result Get(size_t *out_size, void *dst, size_t dst_size, const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
u64 size;
|
||||
R_TRY(this->interface->Get(std::addressof(size), key, sf::OutBuffer(dst, dst_size)));
|
||||
|
||||
*out_size = size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
/* TODO: Proper ProgramId vs DataId vs ApplicationId for Get */
|
||||
#define AMS_NCM_DEFINE_GETTERS(Kind) \
|
||||
Result Get##Kind(ContentId *out, ProgramId id, u32 version) { \
|
||||
return this->interface->GetContentIdByType(out, ContentMetaKey::MakeUnknownType(id, version), ContentType::Kind); \
|
||||
} \
|
||||
\
|
||||
Result GetLatest##Kind(ContentId *out, ProgramId id) { \
|
||||
ContentMetaKey latest_key; \
|
||||
R_TRY(this->interface->GetLatestContentMetaKey(std::addressof(latest_key), id)); \
|
||||
return this->interface->GetContentIdByType(out, latest_key, ContentType::Kind); \
|
||||
}
|
||||
|
||||
AMS_NCM_DEFINE_GETTERS(Program)
|
||||
AMS_NCM_DEFINE_GETTERS(Data)
|
||||
AMS_NCM_DEFINE_GETTERS(Control)
|
||||
AMS_NCM_DEFINE_GETTERS(HtmlDocument)
|
||||
AMS_NCM_DEFINE_GETTERS(LegalInformation)
|
||||
|
||||
#undef AMS_NCM_DEFINE_GETTERS
|
||||
|
||||
/* TODO: Remove(SystemProgramId) Remove(SystemDataId) Remove(ProgramId) */
|
||||
|
||||
Result Remove(const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->Remove(key);
|
||||
}
|
||||
|
||||
Result GetContentIdByType(ContentId *out_content_id, const ContentMetaKey &key, ContentType type) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetContentIdByType(out_content_id, key, type);
|
||||
}
|
||||
|
||||
Result GetContentIdByTypeAndIdOffset(ContentId *out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetContentIdByTypeAndIdOffset(out_content_id, key, type, id_offset);
|
||||
}
|
||||
|
||||
ListCount ListApplication(ApplicationContentMetaKey *dst, size_t dst_size) {
|
||||
ListCount lc = {};
|
||||
R_ABORT_UNLESS(this->interface->ListApplication(std::addressof(lc.total), std::addressof(lc.written), sf::OutArray<ApplicationContentMetaKey>(dst, dst_size), ContentMetaType::Unknown));
|
||||
return lc;
|
||||
}
|
||||
|
||||
ListCount ListContentMeta(ContentMetaKey *dst, size_t dst_size, ContentMetaType type, ProgramId app_id, ProgramId min, ProgramId max, ContentInstallType install_type) {
|
||||
ListCount lc = {};
|
||||
R_ABORT_UNLESS(this->interface->List(std::addressof(lc.total), std::addressof(lc.written), sf::OutArray<ContentMetaKey>(dst, dst_size), type, app_id, min, max, install_type));
|
||||
return lc;
|
||||
}
|
||||
|
||||
Result GetLatest(ContentMetaKey *out_key, ProgramId id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetLatestContentMetaKey(out_key, id);
|
||||
}
|
||||
|
||||
Result ListContentInfo(u32 *out_count, ContentInfo *dst, size_t dst_size, const ContentMetaKey &key, u32 offset) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->ListContentInfo(out_count, sf::OutArray<ContentInfo>(dst, dst_size), key, offset);
|
||||
}
|
||||
|
||||
Result ListContentMetaInfo(u32 *out_count, ContentMetaInfo *dst, size_t dst_size, const ContentMetaKey &key, u32 offset) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->ListContentMetaInfo(out_count, sf::OutArray<ContentMetaInfo>(dst, dst_size), key, offset);
|
||||
}
|
||||
|
||||
Result Has(bool *out, const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->Has(out, key);
|
||||
}
|
||||
|
||||
Result HasAll(bool *out, const ContentMetaKey *keys, size_t num_keys) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->HasAll(out, sf::InArray<ContentMetaKey>(keys, num_keys));
|
||||
}
|
||||
|
||||
Result HasContent(bool *out, const ContentMetaKey &key, const ContentId &content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->HasContent(out, key, content_id);
|
||||
}
|
||||
|
||||
Result GetSize(size_t *out_size, const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
u64 size;
|
||||
R_TRY(this->interface->GetSize(std::addressof(size), key));
|
||||
|
||||
*out_size = size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result GetRequiredSystemVersion(u32 *out_version, const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetRequiredSystemVersion(out_version, key);
|
||||
}
|
||||
|
||||
Result GetPatchId(ProgramId *out_patch_id, const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetPatchId(out_patch_id, key);
|
||||
}
|
||||
|
||||
Result DisableForcibly() {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->DisableForcibly();
|
||||
}
|
||||
|
||||
Result LookupOrphanContent(bool *out_orphaned, ContentId *content_list, size_t count) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->LookupOrphanContent(sf::OutArray<bool>(out_orphaned, count), sf::InArray<ContentId>(content_list, count));
|
||||
}
|
||||
|
||||
Result Commit() {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->Commit();
|
||||
}
|
||||
|
||||
Result GetAttributes(ContentMetaAttribute *out_attributes, const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetAttributes(out_attributes, key);
|
||||
}
|
||||
|
||||
Result GetRequiredApplicationVersion(u32 *out_version, const ContentMetaKey &key) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetRequiredApplicationVersion(out_version, key);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* 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/ncm/ncm_types.hpp>
|
||||
#include <stratosphere/ncm/ncm_i_content_storage.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
class ContentStorage {
|
||||
NON_COPYABLE(ContentStorage);
|
||||
private:
|
||||
std::shared_ptr<IContentStorage> interface;
|
||||
public:
|
||||
ContentStorage() { /* ... */ }
|
||||
explicit ContentStorage(std::shared_ptr<IContentStorage> intf) : interface(std::move(intf)) { /* ... */ }
|
||||
|
||||
ContentStorage(ContentStorage &&rhs) {
|
||||
this->interface = std::move(rhs.interface);
|
||||
}
|
||||
|
||||
ContentStorage &operator=(ContentStorage &&rhs) {
|
||||
ContentStorage(std::move(rhs)).Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Swap(ContentStorage &rhs) {
|
||||
std::swap(this->interface, rhs.interface);
|
||||
}
|
||||
public:
|
||||
PlaceHolderId GeneratePlaceHolderId() {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
|
||||
PlaceHolderId id;
|
||||
R_ABORT_UNLESS(this->interface->GeneratePlaceHolderId(std::addressof(id)));
|
||||
return id;
|
||||
}
|
||||
|
||||
Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->CreatePlaceHolder(placeholder_id, content_id, size);
|
||||
}
|
||||
|
||||
Result DeletePlaceHolder(PlaceHolderId placeholder_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->DeletePlaceHolder(placeholder_id);
|
||||
}
|
||||
|
||||
Result HasPlaceHolder(bool *out, PlaceHolderId placeholder_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->HasPlaceHolder(out, placeholder_id);
|
||||
}
|
||||
|
||||
Result WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, const void *buf, size_t size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->WritePlaceHolder(placeholder_id, offset, sf::InBuffer(buf, size));
|
||||
}
|
||||
|
||||
Result Register(PlaceHolderId placeholder_id, ContentId content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->Register(placeholder_id, content_id);
|
||||
}
|
||||
|
||||
Result Delete(ContentId content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->Delete(content_id);
|
||||
}
|
||||
|
||||
Result Has(bool *out, ContentId content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->Has(out, content_id);
|
||||
}
|
||||
|
||||
void GetPath(Path *out, ContentId content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
R_ABORT_UNLESS(this->interface->GetPath(out, content_id));
|
||||
}
|
||||
|
||||
void GetPlaceHolderPath(Path *out, PlaceHolderId placeholder_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
R_ABORT_UNLESS(this->interface->GetPlaceHolderPath(out, placeholder_id));
|
||||
}
|
||||
|
||||
Result CleanupAllPlaceHolder() {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->CleanupAllPlaceHolder();
|
||||
}
|
||||
|
||||
Result ListPlaceHolder(u32 *out_count, PlaceHolderId *out_list, size_t out_list_size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->ListPlaceHolder(out_count, sf::OutArray<PlaceHolderId>(out_list, out_list_size));
|
||||
}
|
||||
|
||||
Result GetContentCount(u32 *out_count) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetContentCount(out_count);
|
||||
}
|
||||
|
||||
Result ListContentId(u32 *out_count, ContentId *out_list, size_t out_list_size, u32 offset) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->ListContentId(out_count, sf::OutArray<ContentId>(out_list, out_list_size), offset);
|
||||
}
|
||||
|
||||
Result GetSize(u64 *out_size, ContentId content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetSizeFromContentId(out_size, content_id);
|
||||
}
|
||||
|
||||
Result GetSize(u64 *out_size, PlaceHolderId placeholder_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetSizeFromPlaceHolderId(out_size, placeholder_id);
|
||||
}
|
||||
|
||||
Result DisableForcibly() {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->DisableForcibly();
|
||||
}
|
||||
|
||||
Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->RevertToPlaceHolder(placeholder_id, old_content_id, new_content_id);
|
||||
}
|
||||
|
||||
Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->SetPlaceHolderSize(placeholder_id, size);
|
||||
}
|
||||
|
||||
Result ReadContentIdFile(void *dst, size_t size, ContentId content_id, u64 offset) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->ReadContentIdFile(sf::OutBuffer(dst, size), content_id, offset);
|
||||
}
|
||||
|
||||
Result GetRightsId(ams::fs::RightsId *out_rights_id, PlaceHolderId placeholder_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
AMS_ABORT_UNLESS(hos::GetVersion() < hos::Version_300);
|
||||
return this->interface->GetRightsIdFromPlaceHolderIdDeprecated(out_rights_id, placeholder_id);
|
||||
}
|
||||
|
||||
Result GetRightsId(ncm::RightsId *out_rights_id, PlaceHolderId placeholder_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
AMS_ABORT_UNLESS(hos::GetVersion() >= hos::Version_300);
|
||||
return this->interface->GetRightsIdFromPlaceHolderId(out_rights_id, placeholder_id);
|
||||
}
|
||||
|
||||
Result GetRightsId(ams::fs::RightsId *out_rights_id, ContentId content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
AMS_ABORT_UNLESS(hos::GetVersion() < hos::Version_300);
|
||||
return this->interface->GetRightsIdFromContentIdDeprecated(out_rights_id, content_id);
|
||||
}
|
||||
|
||||
Result GetRightsId(ncm::RightsId *out_rights_id, ContentId content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
AMS_ABORT_UNLESS(hos::GetVersion() >= hos::Version_300);
|
||||
return this->interface->GetRightsIdFromContentId(out_rights_id, content_id);
|
||||
}
|
||||
|
||||
Result WriteContentForDebug(ContentId content_id, u64 offset, const void *buf, size_t size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->WriteContentForDebug(content_id, offset, sf::InBuffer(buf, size));
|
||||
}
|
||||
|
||||
Result GetFreeSpaceSize(u64 *out_size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetFreeSpaceSize(out_size);
|
||||
}
|
||||
|
||||
Result GetTotalSpaceSize(u64 *out_size) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetTotalSpaceSize(out_size);
|
||||
}
|
||||
|
||||
Result FlushPlaceHolder() {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->FlushPlaceHolder();
|
||||
}
|
||||
|
||||
Result RepairInvalidFileAttribute() {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->RepairInvalidFileAttribute();
|
||||
}
|
||||
|
||||
Result GetRightsIdFromPlaceHolderIdWithCache(ncm::RightsId *out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) {
|
||||
AMS_ASSERT(this->interface != nullptr);
|
||||
return this->interface->GetRightsIdFromPlaceHolderIdWithCache(out_rights_id, placeholder_id, cache_content_id);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -15,12 +15,12 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
#include <stratosphere/ncm/ncm_i_content_storage.hpp>
|
||||
#include <stratosphere/ncm/ncm_i_content_meta_database.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
class ContentManagerService final : public sf::IServiceObject {
|
||||
class IContentManager : public sf::IServiceObject {
|
||||
protected:
|
||||
enum class CommandId {
|
||||
CreateContentStorage = 0,
|
||||
|
@ -39,20 +39,20 @@ namespace ams::ncm {
|
|||
InvalidateRightsIdCache = 13,
|
||||
};
|
||||
public:
|
||||
Result CreateContentStorage(StorageId storage_id);
|
||||
Result CreateContentMetaDatabase(StorageId storage_id);
|
||||
Result VerifyContentStorage(StorageId storage_id);
|
||||
Result VerifyContentMetaDatabase(StorageId storage_id);
|
||||
Result OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id);
|
||||
Result OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id);
|
||||
Result CloseContentStorageForcibly(StorageId storage_id);
|
||||
Result CloseContentMetaDatabaseForcibly(StorageId storage_id);
|
||||
Result CleanupContentMetaDatabase(StorageId storage_id);
|
||||
Result ActivateContentStorage(StorageId storage_id);
|
||||
Result InactivateContentStorage(StorageId storage_id);
|
||||
Result ActivateContentMetaDatabase(StorageId storage_id);
|
||||
Result InactivateContentMetaDatabase(StorageId storage_id);
|
||||
Result InvalidateRightsIdCache();
|
||||
virtual Result CreateContentStorage(StorageId storage_id) = 0;
|
||||
virtual Result CreateContentMetaDatabase(StorageId storage_id) = 0;
|
||||
virtual Result VerifyContentStorage(StorageId storage_id) = 0;
|
||||
virtual Result VerifyContentMetaDatabase(StorageId storage_id) = 0;
|
||||
virtual Result OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id) = 0;
|
||||
virtual Result OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id) = 0;
|
||||
virtual Result CloseContentStorageForcibly(StorageId storage_id) = 0;
|
||||
virtual Result CloseContentMetaDatabaseForcibly(StorageId storage_id) = 0;
|
||||
virtual Result CleanupContentMetaDatabase(StorageId storage_id) = 0;
|
||||
virtual Result ActivateContentStorage(StorageId storage_id) = 0;
|
||||
virtual Result InactivateContentStorage(StorageId storage_id) = 0;
|
||||
virtual Result ActivateContentMetaDatabase(StorageId storage_id) = 0;
|
||||
virtual Result InactivateContentMetaDatabase(StorageId storage_id) = 0;
|
||||
virtual Result InvalidateRightsIdCache() = 0;
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(CreateContentStorage),
|
|
@ -64,7 +64,7 @@ namespace ams::ncm {
|
|||
virtual Result DisableForcibly() = 0;
|
||||
virtual Result LookupOrphanContent(const sf::OutArray<bool> &out_orphaned, const sf::InArray<ContentId> &content_ids) = 0;
|
||||
virtual Result Commit() = 0;
|
||||
virtual Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, ContentId content_id) = 0;
|
||||
virtual Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, const ContentId &content_id) = 0;
|
||||
virtual Result ListContentMetaInfo(sf::Out<u32> out_entries_written, const sf::OutArray<ContentMetaInfo> &out_meta_info, const ContentMetaKey &key, u32 start_index) = 0;
|
||||
virtual Result GetAttributes(sf::Out<ContentMetaAttribute> out_attributes, const ContentMetaKey &key) = 0;
|
||||
virtual Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key) = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <stratosphere/ncm/ncm_types.hpp>
|
||||
#include <stratosphere/ncm/ncm_path.hpp>
|
||||
#include <stratosphere/lr/lr_types.hpp>
|
||||
#include <stratosphere/sf.hpp>
|
||||
|
||||
|
@ -68,8 +69,8 @@ namespace ams::ncm {
|
|||
virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) = 0;
|
||||
virtual Result Delete(ContentId content_id) = 0;
|
||||
virtual Result Has(sf::Out<bool> out, ContentId content_id) = 0;
|
||||
virtual Result GetPath(sf::Out<lr::Path> out, ContentId content_id) = 0;
|
||||
virtual Result GetPlaceHolderPath(sf::Out<lr::Path> out, PlaceHolderId placeholder_id) = 0;
|
||||
virtual Result GetPath(sf::Out<Path> out, ContentId content_id) = 0;
|
||||
virtual Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id) = 0;
|
||||
virtual Result CleanupAllPlaceHolder() = 0;
|
||||
virtual Result ListPlaceHolder(sf::Out<u32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) = 0;
|
||||
virtual Result GetContentCount(sf::Out<u32> out_count) = 0;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 <vapours.hpp>
|
||||
#include <stratosphere/ncm/ncm_types.hpp>
|
||||
#include <stratosphere/fs/fs_directory.hpp>
|
||||
#include <stratosphere/sf/sf_buffer_tags.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
struct alignas(4) Path : ams::sf::LargeData {
|
||||
char str[fs::EntryNameLengthMax];
|
||||
|
||||
static constexpr Path Encode(const char *p) {
|
||||
Path path = {};
|
||||
/* Copy C string to path, terminating when a null byte is found. */
|
||||
for (size_t i = 0; i < sizeof(path) - 1; i++) {
|
||||
path.str[i] = p[i];
|
||||
if (p[i] == '\x00') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -621,6 +621,10 @@ namespace ams::ncm {
|
|||
return !(*this == other);
|
||||
}
|
||||
|
||||
static constexpr ContentMetaKey MakeUnknownType(ProgramId program_id, u32 version) {
|
||||
return { .id = program_id, .version = version, .type = ContentMetaType::Unknown };
|
||||
}
|
||||
|
||||
static constexpr ContentMetaKey Make(ProgramId program_id, u32 version, ContentMetaType type) {
|
||||
return { .id = program_id, .version = version, .type = type };
|
||||
}
|
||||
|
|
|
@ -86,11 +86,13 @@ namespace ams::sf {
|
|||
cmif::ServiceObjectHolder *srv;
|
||||
cmif::DomainObjectId *object_id;
|
||||
public:
|
||||
Out(cmif::ServiceObjectHolder *s) : srv(s), object_id(nullptr) { /* ... */ }
|
||||
Out(cmif::ServiceObjectHolder *s, cmif::DomainObjectId *o) : srv(s), object_id(o) { /* ... */ }
|
||||
|
||||
void SetValue(std::shared_ptr<ServiceImpl> &&s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) {
|
||||
*this->srv = cmif::ServiceObjectHolder(std::move(s));
|
||||
if (new_object_id != cmif::InvalidDomainObjectId) {
|
||||
AMS_ABORT_UNLESS(object_id != nullptr);
|
||||
*this->object_id = new_object_id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,6 @@
|
|||
#include <stratosphere.hpp>
|
||||
#include "lr_add_on_content_location_resolver_impl.hpp"
|
||||
|
||||
/* TODO: Properly integrate NCM api into libstratosphere to avoid linker hack. */
|
||||
namespace ams::ncm::impl {
|
||||
|
||||
Result OpenContentMetaDatabase(std::shared_ptr<ncm::IContentMetaDatabase> *, ncm::StorageId);
|
||||
Result OpenContentStorage(std::shared_ptr<ncm::IContentStorage> *, ncm::StorageId);
|
||||
|
||||
}
|
||||
|
||||
namespace ams::lr {
|
||||
|
||||
Result AddOnContentLocationResolverImpl::ResolveAddOnContentPath(sf::Out<Path> out, ncm::ProgramId id) {
|
||||
|
@ -32,19 +24,20 @@ namespace ams::lr {
|
|||
R_UNLESS(this->registered_storages.Find(&storage_id, id), lr::ResultAddOnContentNotFound());
|
||||
|
||||
/* Obtain a Content Meta Database for the storage id. */
|
||||
std::shared_ptr<ncm::IContentMetaDatabase> content_meta_database;
|
||||
R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, storage_id));
|
||||
ncm::ContentMetaDatabase content_meta_database;
|
||||
R_TRY(ncm::OpenContentMetaDatabase(&content_meta_database, storage_id));
|
||||
|
||||
/* Find the latest data content id for the given program id. */
|
||||
ncm::ContentId data_content_id;
|
||||
R_TRY(content_meta_database->GetLatestData(&data_content_id, id));
|
||||
R_TRY(content_meta_database.GetLatestData(&data_content_id, id));
|
||||
|
||||
/* Obtain a Content Storage for the storage id. */
|
||||
std::shared_ptr<ncm::IContentStorage> content_storage;
|
||||
R_TRY(ncm::impl::OpenContentStorage(&content_storage, storage_id));
|
||||
ncm::ContentStorage content_storage;
|
||||
R_TRY(ncm::OpenContentStorage(&content_storage, storage_id));
|
||||
|
||||
/* Get the path of the data content. */
|
||||
R_ABORT_UNLESS(content_storage->GetPath(out.GetPointer(), data_content_id));
|
||||
static_assert(sizeof(lr::Path) == sizeof(ncm::Path));
|
||||
content_storage.GetPath(reinterpret_cast<ncm::Path *>(out.GetPointer()), data_content_id);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
|
|
@ -16,14 +16,6 @@
|
|||
#include <stratosphere.hpp>
|
||||
#include "lr_content_location_resolver_impl.hpp"
|
||||
|
||||
/* TODO: Properly integrate NCM api into libstratosphere to avoid linker hack. */
|
||||
namespace ams::ncm::impl {
|
||||
|
||||
Result OpenContentMetaDatabase(std::shared_ptr<ncm::IContentMetaDatabase> *, ncm::StorageId);
|
||||
Result OpenContentStorage(std::shared_ptr<ncm::IContentStorage> *, ncm::StorageId);
|
||||
|
||||
}
|
||||
|
||||
namespace ams::lr {
|
||||
|
||||
ContentLocationResolverImpl::~ContentLocationResolverImpl() {
|
||||
|
@ -32,7 +24,8 @@ namespace ams::lr {
|
|||
|
||||
/* Helper function. */
|
||||
void ContentLocationResolverImpl::GetContentStoragePath(Path *out, ncm::ContentId content_id) {
|
||||
R_ABORT_UNLESS(this->content_storage->GetPath(out, content_id));
|
||||
static_assert(sizeof(lr::Path) == sizeof(ncm::Path));
|
||||
this->content_storage.GetPath(reinterpret_cast<ncm::Path *>(out), content_id);
|
||||
}
|
||||
|
||||
Result ContentLocationResolverImpl::ResolveProgramPath(sf::Out<Path> out, ncm::ProgramId id) {
|
||||
|
@ -41,7 +34,7 @@ namespace ams::lr {
|
|||
|
||||
/* Find the latest program content for the program id. */
|
||||
ncm::ContentId program_content_id;
|
||||
R_TRY_CATCH(this->content_meta_database->GetLatestProgram(&program_content_id, id)) {
|
||||
R_TRY_CATCH(this->content_meta_database.GetLatestProgram(&program_content_id, id)) {
|
||||
R_CONVERT(ncm::ResultContentMetaNotFound, lr::ResultProgramNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
|
@ -69,7 +62,7 @@ namespace ams::lr {
|
|||
Result ContentLocationResolverImpl::ResolveDataPath(sf::Out<Path> out, ncm::ProgramId id) {
|
||||
/* Find the latest data content for the program id. */
|
||||
ncm::ContentId data_content_id;
|
||||
R_TRY(this->content_meta_database->GetLatestData(&data_content_id, id));
|
||||
R_TRY(this->content_meta_database.GetLatestData(&data_content_id, id));
|
||||
|
||||
/* Obtain the content path. */
|
||||
this->GetContentStoragePath(out.GetPointer(), data_content_id);
|
||||
|
@ -114,14 +107,14 @@ namespace ams::lr {
|
|||
|
||||
Result ContentLocationResolverImpl::Refresh() {
|
||||
/* Obtain Content Meta Database and Content Storage objects for this resolver's storage. */
|
||||
std::shared_ptr<ncm::IContentMetaDatabase> content_meta_database;
|
||||
std::shared_ptr<ncm::IContentStorage> content_storage;
|
||||
R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id));
|
||||
R_TRY(ncm::impl::OpenContentStorage(&content_storage, this->storage_id));
|
||||
ncm::ContentMetaDatabase meta_db;
|
||||
ncm::ContentStorage storage;
|
||||
R_TRY(ncm::OpenContentMetaDatabase(&meta_db, this->storage_id));
|
||||
R_TRY(ncm::OpenContentStorage(&storage, this->storage_id));
|
||||
|
||||
/* Store the acquired objects. */
|
||||
this->content_meta_database = std::move(content_meta_database);
|
||||
this->content_storage = std::move(content_storage);
|
||||
this->content_meta_database = std::move(meta_db);
|
||||
this->content_storage = std::move(storage);
|
||||
|
||||
/* Remove any existing redirections. */
|
||||
this->ClearRedirections();
|
||||
|
|
|
@ -24,8 +24,8 @@ namespace ams::lr {
|
|||
ncm::StorageId storage_id;
|
||||
|
||||
/* Objects for this storage type. */
|
||||
std::shared_ptr<ncm::IContentMetaDatabase> content_meta_database;
|
||||
std::shared_ptr<ncm::IContentStorage> content_storage;
|
||||
ncm::ContentMetaDatabase content_meta_database;
|
||||
ncm::ContentStorage content_storage;
|
||||
public:
|
||||
ContentLocationResolverImpl(ncm::StorageId storage_id) : storage_id(storage_id) { /* ... */ }
|
||||
|
||||
|
|
112
libraries/libstratosphere/source/ncm/ncm_api.cpp
Normal file
112
libraries/libstratosphere/source/ncm/ncm_api.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "ncm_remote_content_manager_impl.hpp"
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
namespace {
|
||||
|
||||
std::shared_ptr<IContentManager> g_content_manager;
|
||||
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
AMS_ASSERT(g_content_manager == nullptr);
|
||||
R_ABORT_UNLESS(ncmInitialize());
|
||||
g_content_manager = std::make_shared<RemoteContentManagerImpl>();
|
||||
}
|
||||
|
||||
void Finalize() {
|
||||
AMS_ASSERT(g_content_manager != nullptr);
|
||||
g_content_manager.reset();
|
||||
ncmExit();
|
||||
}
|
||||
|
||||
void InitializeWithObject(std::shared_ptr<IContentManager> manager_object) {
|
||||
AMS_ASSERT(g_content_manager == nullptr);
|
||||
g_content_manager = manager_object;
|
||||
AMS_ASSERT(g_content_manager != nullptr);
|
||||
}
|
||||
|
||||
/* Service API. */
|
||||
Result CreateContentStorage(StorageId storage_id) {
|
||||
return g_content_manager->CreateContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result CreateContentMetaDatabase(StorageId storage_id) {
|
||||
return g_content_manager->CreateContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result VerifyContentStorage(StorageId storage_id) {
|
||||
return g_content_manager->VerifyContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result VerifyContentMetaDatabase(StorageId storage_id) {
|
||||
return g_content_manager->VerifyContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result OpenContentStorage(ContentStorage *out, StorageId storage_id) {
|
||||
sf::cmif::ServiceObjectHolder object_holder;
|
||||
R_TRY(g_content_manager->OpenContentStorage(std::addressof(object_holder), storage_id));
|
||||
|
||||
*out = ContentStorage(object_holder.GetServiceObject<IContentStorage>());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result OpenContentMetaDatabase(ContentMetaDatabase *out, StorageId storage_id) {
|
||||
sf::cmif::ServiceObjectHolder object_holder;
|
||||
R_TRY(g_content_manager->OpenContentMetaDatabase(std::addressof(object_holder), storage_id));
|
||||
|
||||
*out = ContentMetaDatabase(object_holder.GetServiceObject<IContentMetaDatabase>());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result CleanupContentMetaDatabase(StorageId storage_id) {
|
||||
return g_content_manager->CleanupContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result ActivateContentStorage(StorageId storage_id) {
|
||||
return g_content_manager->ActivateContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result InactivateContentStorage(StorageId storage_id) {
|
||||
return g_content_manager->InactivateContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result ActivateContentMetaDatabase(StorageId storage_id) {
|
||||
return g_content_manager->ActivateContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result InactivateContentMetaDatabase(StorageId storage_id) {
|
||||
return g_content_manager->InactivateContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result InvalidateRightsIdCache() {
|
||||
return g_content_manager->InvalidateRightsIdCache();
|
||||
}
|
||||
|
||||
/* Deprecated API. */
|
||||
Result CloseContentStorageForcibly(StorageId storage_id) {
|
||||
AMS_ABORT_UNLESS(hos::GetVersion() == hos::Version_100);
|
||||
return g_content_manager->CloseContentStorageForcibly(storage_id);
|
||||
}
|
||||
|
||||
Result CloseContentMetaDatabaseForcibly(StorageId storage_id) {
|
||||
AMS_ABORT_UNLESS(hos::GetVersion() == hos::Version_100);
|
||||
return g_content_manager->CloseContentMetaDatabaseForcibly(storage_id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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>
|
||||
#include "ncm_remote_content_storage_impl.hpp"
|
||||
#include "ncm_remote_content_meta_database_impl.hpp"
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
class RemoteContentManagerImpl final : public IContentManager {
|
||||
public:
|
||||
RemoteContentManagerImpl() { /* ... */ }
|
||||
|
||||
~RemoteContentManagerImpl() { /* ... */ }
|
||||
public:
|
||||
virtual Result CreateContentStorage(StorageId storage_id) override {
|
||||
return ::ncmCreateContentStorage(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result CreateContentMetaDatabase(StorageId storage_id) override {
|
||||
return ::ncmCreateContentMetaDatabase(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result VerifyContentStorage(StorageId storage_id) override {
|
||||
return ::ncmVerifyContentStorage(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result VerifyContentMetaDatabase(StorageId storage_id) override {
|
||||
return ::ncmVerifyContentMetaDatabase(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id) override {
|
||||
NcmContentStorage cs;
|
||||
R_TRY(::ncmOpenContentStorage(std::addressof(cs), static_cast<NcmStorageId>(storage_id)));
|
||||
|
||||
out.SetValue(std::make_shared<RemoteContentStorageImpl>(cs));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id) override {
|
||||
NcmContentMetaDatabase db;
|
||||
R_TRY(::ncmOpenContentMetaDatabase(std::addressof(db), static_cast<NcmStorageId>(storage_id)));
|
||||
|
||||
out.SetValue(std::make_shared<RemoteContentMetaDatabaseImpl>(db));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result CloseContentStorageForcibly(StorageId storage_id) override {
|
||||
return ::ncmCloseContentStorageForcibly(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result CloseContentMetaDatabaseForcibly(StorageId storage_id) override {
|
||||
return ::ncmCloseContentMetaDatabaseForcibly(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result CleanupContentMetaDatabase(StorageId storage_id) override {
|
||||
return ::ncmCleanupContentMetaDatabase(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result ActivateContentStorage(StorageId storage_id) override {
|
||||
return ::ncmActivateContentStorage(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result InactivateContentStorage(StorageId storage_id) override {
|
||||
return ::ncmInactivateContentStorage(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result ActivateContentMetaDatabase(StorageId storage_id) override {
|
||||
return ::ncmActivateContentMetaDatabase(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result InactivateContentMetaDatabase(StorageId storage_id) override {
|
||||
return ::ncmInactivateContentMetaDatabase(static_cast<NcmStorageId>(storage_id));
|
||||
}
|
||||
|
||||
virtual Result InvalidateRightsIdCache() override {
|
||||
return ::ncmInvalidateRightsIdCache();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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 RemoteContentMetaDatabaseImpl final : public IContentMetaDatabase {
|
||||
private:
|
||||
::NcmContentMetaDatabase srv;
|
||||
public:
|
||||
RemoteContentMetaDatabaseImpl(::NcmContentMetaDatabase &db) : srv(db) { /* ... */ }
|
||||
|
||||
~RemoteContentMetaDatabaseImpl() { ::ncmContentMetaDatabaseClose(std::addressof(srv)); }
|
||||
private:
|
||||
ALWAYS_INLINE ::NcmContentMetaKey *Convert(ContentMetaKey *k) {
|
||||
static_assert(sizeof(ContentMetaKey) == sizeof(::NcmContentMetaKey));
|
||||
return reinterpret_cast<::NcmContentMetaKey *>(k);
|
||||
}
|
||||
ALWAYS_INLINE const ::NcmContentMetaKey *Convert(const ContentMetaKey *k) {
|
||||
static_assert(sizeof(ContentMetaKey) == sizeof(::NcmContentMetaKey));
|
||||
return reinterpret_cast<const ::NcmContentMetaKey *>(k);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const ::NcmContentMetaKey *Convert(const ContentMetaKey &k) {
|
||||
static_assert(sizeof(ContentMetaKey) == sizeof(::NcmContentMetaKey));
|
||||
return reinterpret_cast<const ::NcmContentMetaKey *>(std::addressof(k));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ::NcmApplicationContentMetaKey *Convert(ApplicationContentMetaKey *k) {
|
||||
static_assert(sizeof(ApplicationContentMetaKey) == sizeof(::NcmApplicationContentMetaKey));
|
||||
return reinterpret_cast<::NcmApplicationContentMetaKey *>(k);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ::NcmContentInfo *Convert(ContentInfo *c) {
|
||||
static_assert(sizeof(ContentInfo) == sizeof(::NcmContentInfo));
|
||||
return reinterpret_cast<::NcmContentInfo *>(c);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ::NcmContentId *Convert(ContentId *c) {
|
||||
static_assert(sizeof(ContentId) == sizeof(::NcmContentId));
|
||||
return reinterpret_cast<::NcmContentId *>(c);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ::NcmContentId *Convert(ContentId &c) {
|
||||
static_assert(sizeof(ContentId) == sizeof(::NcmContentId));
|
||||
return reinterpret_cast<::NcmContentId *>(std::addressof(c));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const ::NcmContentId *Convert(const ContentId *c) {
|
||||
static_assert(sizeof(ContentId) == sizeof(::NcmContentId));
|
||||
return reinterpret_cast<const ::NcmContentId *>(c);
|
||||
}
|
||||
|
||||
|
||||
ALWAYS_INLINE const ::NcmContentId *Convert(const ContentId &c) {
|
||||
static_assert(sizeof(ContentId) == sizeof(::NcmContentId));
|
||||
return reinterpret_cast<const ::NcmContentId *>(std::addressof(c));
|
||||
}
|
||||
public:
|
||||
virtual Result Set(const ContentMetaKey &key, sf::InBuffer value) override {
|
||||
return ncmContentMetaDatabaseSet(std::addressof(this->srv), Convert(key), value.GetPointer(), value.GetSize());
|
||||
}
|
||||
|
||||
virtual Result Get(sf::Out<u64> out_size, const ContentMetaKey &key, sf::OutBuffer out_value) override {
|
||||
return ncmContentMetaDatabaseGet(std::addressof(this->srv), Convert(key), out_size.GetPointer(), out_value.GetPointer(), out_value.GetSize());
|
||||
}
|
||||
|
||||
virtual Result Remove(const ContentMetaKey &key) override {
|
||||
return ncmContentMetaDatabaseRemove(std::addressof(this->srv), Convert(key));
|
||||
}
|
||||
|
||||
virtual Result GetContentIdByType(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type) override {
|
||||
return ncmContentMetaDatabaseGetContentIdByType(std::addressof(this->srv), Convert(out_content_id.GetPointer()), Convert(key), static_cast<::NcmContentType>(type));
|
||||
}
|
||||
|
||||
virtual Result ListContentInfo(sf::Out<u32> out_entries_written, const sf::OutArray<ContentInfo> &out_info, const ContentMetaKey &key, u32 start_index) override {
|
||||
return ncmContentMetaDatabaseListContentInfo(std::addressof(this->srv), reinterpret_cast<s32 *>(out_entries_written.GetPointer()), Convert(out_info.GetPointer()), out_info.GetSize(), Convert(key), start_index);
|
||||
}
|
||||
|
||||
virtual Result List(sf::Out<u32> out_entries_total, sf::Out<u32> out_entries_written, const sf::OutArray<ContentMetaKey> &out, ContentMetaType meta_type, ProgramId application_program_id, ProgramId program_id_min, ProgramId program_id_max, ContentInstallType install_type) override {
|
||||
return ncmContentMetaDatabaseList(std::addressof(this->srv), reinterpret_cast<s32 *>(out_entries_total.GetPointer()), reinterpret_cast<s32 *>(out_entries_written.GetPointer()), Convert(out.GetPointer()), out.GetSize(), static_cast<::NcmContentMetaType>(meta_type), static_cast<u64>(application_program_id), static_cast<u64>(program_id_min), static_cast<u64>(program_id_max), static_cast<::NcmContentInstallType>(install_type));
|
||||
}
|
||||
|
||||
virtual Result GetLatestContentMetaKey(sf::Out<ContentMetaKey> out_key, ProgramId id) override {
|
||||
return ncmContentMetaDatabaseGetLatestContentMetaKey(std::addressof(this->srv), Convert(out_key.GetPointer()), static_cast<u64>(id));
|
||||
}
|
||||
|
||||
virtual Result ListApplication(sf::Out<u32> out_entries_total, sf::Out<u32> out_entries_written, const sf::OutArray<ApplicationContentMetaKey> &out_keys, ContentMetaType meta_type) override {
|
||||
return ncmContentMetaDatabaseListApplication(std::addressof(this->srv), reinterpret_cast<s32 *>(out_entries_total.GetPointer()), reinterpret_cast<s32 *>(out_entries_written.GetPointer()), Convert(out_keys.GetPointer()), out_keys.GetSize(), static_cast<::NcmContentMetaType>(meta_type));
|
||||
}
|
||||
|
||||
virtual Result Has(sf::Out<bool> out, const ContentMetaKey &key) override {
|
||||
return ncmContentMetaDatabaseHas(std::addressof(this->srv), out.GetPointer(), Convert(key));
|
||||
}
|
||||
|
||||
virtual Result HasAll(sf::Out<bool> out, const sf::InArray<ContentMetaKey> &keys) override {
|
||||
return ncmContentMetaDatabaseHasAll(std::addressof(this->srv), out.GetPointer(), Convert(keys.GetPointer()), keys.GetSize());
|
||||
}
|
||||
|
||||
virtual Result GetSize(sf::Out<u64> out_size, const ContentMetaKey &key) override {
|
||||
return ncmContentMetaDatabaseGetSize(std::addressof(this->srv), out_size.GetPointer(), Convert(key));
|
||||
}
|
||||
|
||||
virtual Result GetRequiredSystemVersion(sf::Out<u32> out_version, const ContentMetaKey &key) override {
|
||||
return ncmContentMetaDatabaseGetRequiredSystemVersion(std::addressof(this->srv), out_version.GetPointer(), Convert(key));
|
||||
}
|
||||
|
||||
virtual Result GetPatchId(sf::Out<ProgramId> out_patch_id, const ContentMetaKey &key) override {
|
||||
return ncmContentMetaDatabaseGetPatchId(std::addressof(this->srv), reinterpret_cast<u64 *>(out_patch_id.GetPointer()), Convert(key));
|
||||
}
|
||||
|
||||
virtual Result DisableForcibly() override {
|
||||
return ncmContentMetaDatabaseDisableForcibly(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
virtual Result LookupOrphanContent(const sf::OutArray<bool> &out_orphaned, const sf::InArray<ContentId> &content_ids) override {
|
||||
return ncmContentMetaDatabaseLookupOrphanContent(std::addressof(this->srv), out_orphaned.GetPointer(), Convert(content_ids.GetPointer()), std::min(out_orphaned.GetSize(), content_ids.GetSize()));
|
||||
}
|
||||
|
||||
virtual Result Commit() override {
|
||||
return ncmContentMetaDatabaseCommit(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
virtual Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, const ContentId &content_id) override {
|
||||
return ncmContentMetaDatabaseHasContent(std::addressof(this->srv), out.GetPointer(), Convert(key), Convert(content_id));
|
||||
}
|
||||
|
||||
virtual Result ListContentMetaInfo(sf::Out<u32> out_entries_written, const sf::OutArray<ContentMetaInfo> &out_meta_info, const ContentMetaKey &key, u32 start_index) override {
|
||||
return ncmContentMetaDatabaseListContentMetaInfo(std::addressof(this->srv), reinterpret_cast<s32 *>(out_entries_written.GetPointer()), out_meta_info.GetPointer(), out_meta_info.GetSize(), Convert(key), start_index);
|
||||
}
|
||||
|
||||
virtual Result GetAttributes(sf::Out<ContentMetaAttribute> out_attributes, const ContentMetaKey &key) override {
|
||||
static_assert(sizeof(ContentMetaAttribute) == sizeof(u8));
|
||||
return ncmContentMetaDatabaseGetAttributes(std::addressof(this->srv), Convert(key), reinterpret_cast<u8 *>(out_attributes.GetPointer()));
|
||||
}
|
||||
|
||||
virtual Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key) override {
|
||||
return ncmContentMetaDatabaseGetRequiredApplicationVersion(std::addressof(this->srv), out_version.GetPointer(), Convert(key));
|
||||
}
|
||||
|
||||
virtual Result GetContentIdByTypeAndIdOffset(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) override {
|
||||
return ncmContentMetaDatabaseGetContentIdByTypeAndIdOffset(std::addressof(this->srv), Convert(out_content_id.GetPointer()), Convert(key), static_cast<::NcmContentType>(type), id_offset);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* 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 RemoteContentStorageImpl final : public IContentStorage {
|
||||
private:
|
||||
::NcmContentStorage srv;
|
||||
public:
|
||||
RemoteContentStorageImpl(::NcmContentStorage &cs) : srv(cs) { /* ... */ }
|
||||
|
||||
~RemoteContentStorageImpl() { ::ncmContentStorageClose(std::addressof(srv)); }
|
||||
private:
|
||||
ALWAYS_INLINE ::NcmPlaceHolderId *Convert(PlaceHolderId *p) {
|
||||
static_assert(sizeof(PlaceHolderId) == sizeof(::NcmPlaceHolderId));
|
||||
return reinterpret_cast<::NcmPlaceHolderId *>(p);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ::NcmPlaceHolderId *Convert(PlaceHolderId &p) {
|
||||
static_assert(sizeof(PlaceHolderId) == sizeof(::NcmPlaceHolderId));
|
||||
return reinterpret_cast<::NcmPlaceHolderId *>(std::addressof(p));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ::NcmContentId *Convert(ContentId *c) {
|
||||
static_assert(sizeof(ContentId) == sizeof(::NcmContentId));
|
||||
return reinterpret_cast<::NcmContentId *>(c);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ::NcmContentId *Convert(ContentId &c) {
|
||||
static_assert(sizeof(ContentId) == sizeof(::NcmContentId));
|
||||
return reinterpret_cast<::NcmContentId *>(std::addressof(c));
|
||||
}
|
||||
public:
|
||||
virtual Result GeneratePlaceHolderId(sf::Out<PlaceHolderId> out) override {
|
||||
return ncmContentStorageGeneratePlaceHolderId(std::addressof(this->srv), Convert(out.GetPointer()));
|
||||
}
|
||||
|
||||
virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) override {
|
||||
static_assert(alignof(ContentId) < alignof(PlaceHolderId));
|
||||
return ncmContentStorageCreatePlaceHolder(std::addressof(this->srv), Convert(content_id), Convert(placeholder_id), static_cast<s64>(size));
|
||||
}
|
||||
|
||||
virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id) override {
|
||||
return ncmContentStorageDeletePlaceHolder(std::addressof(this->srv), Convert(placeholder_id));
|
||||
}
|
||||
|
||||
virtual Result HasPlaceHolder(sf::Out<bool> out, PlaceHolderId placeholder_id) override {
|
||||
return ncmContentStorageHasPlaceHolder(std::addressof(this->srv), out.GetPointer(), Convert(placeholder_id));
|
||||
}
|
||||
|
||||
virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, sf::InBuffer data) override {
|
||||
return ncmContentStorageWritePlaceHolder(std::addressof(this->srv), Convert(placeholder_id), offset, data.GetPointer(), data.GetSize());
|
||||
}
|
||||
|
||||
virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) override {
|
||||
static_assert(alignof(ContentId) < alignof(PlaceHolderId));
|
||||
return ncmContentStorageRegister(std::addressof(this->srv), Convert(content_id), Convert(placeholder_id));
|
||||
}
|
||||
|
||||
virtual Result Delete(ContentId content_id) override {
|
||||
return ncmContentStorageDelete(std::addressof(this->srv), Convert(content_id));
|
||||
}
|
||||
|
||||
virtual Result Has(sf::Out<bool> out, ContentId content_id) override {
|
||||
return ncmContentStorageHas(std::addressof(this->srv), out.GetPointer(), Convert(content_id));
|
||||
}
|
||||
|
||||
virtual Result GetPath(sf::Out<Path> out, ContentId content_id) override {
|
||||
return ncmContentStorageGetPath(std::addressof(this->srv), out.GetPointer()->str, sizeof(out.GetPointer()->str), Convert(content_id));
|
||||
}
|
||||
|
||||
virtual Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id) override {
|
||||
return ncmContentStorageGetPlaceHolderPath(std::addressof(this->srv), out.GetPointer()->str, sizeof(out.GetPointer()->str), Convert(placeholder_id));
|
||||
}
|
||||
|
||||
virtual Result CleanupAllPlaceHolder() override {
|
||||
return ncmContentStorageCleanupAllPlaceHolder(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
virtual Result ListPlaceHolder(sf::Out<u32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) override {
|
||||
return ncmContentStorageListPlaceHolder(std::addressof(this->srv), Convert(out_buf.GetPointer()), out_buf.GetSize(), reinterpret_cast<s32 *>(out_count.GetPointer()));
|
||||
}
|
||||
|
||||
virtual Result GetContentCount(sf::Out<u32> out_count) override {
|
||||
return ncmContentStorageGetContentCount(std::addressof(this->srv), reinterpret_cast<s32 *>(out_count.GetPointer()));
|
||||
}
|
||||
|
||||
virtual Result ListContentId(sf::Out<u32> out_count, const sf::OutArray<ContentId> &out_buf, u32 offset) override {
|
||||
return ncmContentStorageListContentId(std::addressof(this->srv), Convert(out_buf.GetPointer()), out_buf.GetSize(), reinterpret_cast<s32 *>(out_count.GetPointer()), static_cast<s32>(offset));
|
||||
}
|
||||
|
||||
virtual Result GetSizeFromContentId(sf::Out<u64> out_size, ContentId content_id) override {
|
||||
return ncmContentStorageGetSizeFromContentId(std::addressof(this->srv), reinterpret_cast<s64 *>(out_size.GetPointer()), Convert(content_id));
|
||||
}
|
||||
|
||||
virtual Result DisableForcibly() override {
|
||||
return ncmContentStorageDisableForcibly(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) override {
|
||||
return ncmContentStorageRevertToPlaceHolder(std::addressof(this->srv), Convert(placeholder_id), Convert(old_content_id), Convert(new_content_id));
|
||||
}
|
||||
|
||||
virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) override {
|
||||
return ncmContentStorageSetPlaceHolderSize(std::addressof(this->srv), Convert(placeholder_id), static_cast<s64>(size));
|
||||
}
|
||||
|
||||
virtual Result ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, u64 offset) override {
|
||||
return ncmContentStorageReadContentIdFile(std::addressof(this->srv), buf.GetPointer(), buf.GetSize(), Convert(content_id), static_cast<s64>(offset));
|
||||
}
|
||||
|
||||
virtual Result GetRightsIdFromPlaceHolderIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, PlaceHolderId placeholder_id) override {
|
||||
::NcmRightsId rights_id;
|
||||
R_TRY(ncmContentStorageGetRightsIdFromPlaceHolderId(std::addressof(this->srv), std::addressof(rights_id), Convert(placeholder_id)));
|
||||
|
||||
static_assert(sizeof(*out_rights_id.GetPointer()) <= sizeof(rights_id));
|
||||
std::memcpy(out_rights_id.GetPointer(), std::addressof(rights_id), sizeof(*out_rights_id.GetPointer()));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id) override {
|
||||
::NcmRightsId rights_id;
|
||||
R_TRY(ncmContentStorageGetRightsIdFromPlaceHolderId(std::addressof(this->srv), std::addressof(rights_id), Convert(placeholder_id)));
|
||||
|
||||
static_assert(sizeof(*out_rights_id.GetPointer()) <= sizeof(rights_id));
|
||||
std::memcpy(out_rights_id.GetPointer(), std::addressof(rights_id), sizeof(*out_rights_id.GetPointer()));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result GetRightsIdFromContentIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, ContentId content_id) override {
|
||||
::NcmRightsId rights_id;
|
||||
R_TRY(ncmContentStorageGetRightsIdFromContentId(std::addressof(this->srv), std::addressof(rights_id), Convert(content_id)));
|
||||
|
||||
static_assert(sizeof(*out_rights_id.GetPointer()) <= sizeof(rights_id));
|
||||
std::memcpy(out_rights_id.GetPointer(), std::addressof(rights_id), sizeof(*out_rights_id.GetPointer()));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id) override {
|
||||
::NcmRightsId rights_id;
|
||||
R_TRY(ncmContentStorageGetRightsIdFromContentId(std::addressof(this->srv), std::addressof(rights_id), Convert(content_id)));
|
||||
|
||||
static_assert(sizeof(*out_rights_id.GetPointer()) <= sizeof(rights_id));
|
||||
std::memcpy(out_rights_id.GetPointer(), std::addressof(rights_id), sizeof(*out_rights_id.GetPointer()));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result WriteContentForDebug(ContentId content_id, u64 offset, sf::InBuffer data) override {
|
||||
return ncmContentStorageWriteContentForDebug(std::addressof(this->srv), Convert(content_id), static_cast<s64>(offset), data.GetPointer(), data.GetSize());
|
||||
}
|
||||
|
||||
virtual Result GetFreeSpaceSize(sf::Out<u64> out_size) override {
|
||||
return ncmContentStorageGetFreeSpaceSize(std::addressof(this->srv), reinterpret_cast<s64 *>(out_size.GetPointer()));
|
||||
}
|
||||
|
||||
virtual Result GetTotalSpaceSize(sf::Out<u64> out_size) override {
|
||||
return ncmContentStorageGetTotalSpaceSize(std::addressof(this->srv), reinterpret_cast<s64 *>(out_size.GetPointer()));
|
||||
}
|
||||
|
||||
virtual Result FlushPlaceHolder() override {
|
||||
return ncmContentStorageFlushPlaceHolder(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
virtual Result GetSizeFromPlaceHolderId(sf::Out<u64> out_size, PlaceHolderId placeholder_id) override {
|
||||
return ncmContentStorageGetSizeFromPlaceHolderId(std::addressof(this->srv), reinterpret_cast<s64 *>(out_size.GetPointer()), Convert(placeholder_id));
|
||||
}
|
||||
|
||||
virtual Result RepairInvalidFileAttribute() override {
|
||||
return ncmContentStorageRepairInvalidFileAttribute(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) override {
|
||||
static_assert(sizeof(::NcmRightsId) == sizeof(ncm::RightsId));
|
||||
::NcmRightsId *out = reinterpret_cast<::NcmRightsId *>(out_rights_id.GetPointer());
|
||||
return ncmContentStorageGetRightsIdFromPlaceHolderIdWithCache(std::addressof(this->srv), out, Convert(placeholder_id), Convert(cache_content_id));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -72,7 +72,7 @@ namespace ams::ncm::impl {
|
|||
constexpr u64 BuiltInSystemSaveDataSize = 0x6c000;
|
||||
constexpr u64 BuiltInSystemSaveDataJournalSize = 0x6c000;
|
||||
constexpr u32 BuiltInSystemSaveDataFlags = FsSaveDataFlags_KeepAfterResettingSystemSaveData | FsSaveDataFlags_KeepAfterRefurbishment;
|
||||
|
||||
|
||||
constexpr SaveDataMeta BuiltInSystemSaveDataMeta = {
|
||||
.id = BuiltInSystemSaveDataId,
|
||||
.size = BuiltInSystemSaveDataSize,
|
||||
|
@ -119,7 +119,7 @@ namespace ams::ncm::impl {
|
|||
std::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
|
||||
u32 max_content_metas;
|
||||
|
||||
inline ContentMetaDatabaseEntry() : storage_id(StorageId::None), save_meta({0}),
|
||||
inline ContentMetaDatabaseEntry() : storage_id(StorageId::None), save_meta({0}),
|
||||
content_meta_database(nullptr), kvs(std::nullopt), max_content_metas(0) {
|
||||
mount_point[0] = '\0';
|
||||
meta_path[0] = '\0';
|
||||
|
@ -268,17 +268,17 @@ namespace ams::ncm::impl {
|
|||
/* First, setup the BuiltInSystem storage entry. */
|
||||
g_content_storage_roots[g_num_content_storage_entries++].Initialize(StorageId::BuiltInSystem, FsContentStorageId_System);
|
||||
|
||||
if (R_FAILED(VerifyContentStorage(StorageId::BuiltInSystem))) {
|
||||
R_TRY(CreateContentStorage(StorageId::BuiltInSystem));
|
||||
if (R_FAILED(impl::VerifyContentStorage(StorageId::BuiltInSystem))) {
|
||||
R_TRY(impl::CreateContentStorage(StorageId::BuiltInSystem));
|
||||
}
|
||||
|
||||
R_TRY(ActivateContentStorage(StorageId::BuiltInSystem));
|
||||
R_TRY(impl::ActivateContentStorage(StorageId::BuiltInSystem));
|
||||
|
||||
/* Next, the BuiltInSystem content meta entry. */
|
||||
R_TRY(g_content_meta_entries[g_num_content_meta_entries++].Initialize(StorageId::BuiltInSystem, BuiltInSystemSaveDataMeta, MaxBuiltInSystemContentMetaCount));
|
||||
|
||||
if (R_FAILED(VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
|
||||
R_TRY(CreateContentMetaDatabase(StorageId::BuiltInSystem));
|
||||
if (R_FAILED(impl::VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
|
||||
R_TRY(impl::CreateContentMetaDatabase(StorageId::BuiltInSystem));
|
||||
|
||||
/* TODO: N supports a number of unused modes here, we don't bother implementing them currently. */
|
||||
}
|
||||
|
@ -287,8 +287,8 @@ namespace ams::ncm::impl {
|
|||
if (hos::GetVersion() >= hos::Version_200 && R_SUCCEEDED(fs::GetSaveDataFlags(¤t_flags, BuiltInSystemSaveDataId)) && current_flags != (FsSaveDataFlags_KeepAfterResettingSystemSaveData | FsSaveDataFlags_KeepAfterRefurbishment)) {
|
||||
fs::SetSaveDataFlags(BuiltInSystemSaveDataId, FsSaveDataSpaceId_System, FsSaveDataFlags_KeepAfterResettingSystemSaveData | FsSaveDataFlags_KeepAfterRefurbishment);
|
||||
}
|
||||
|
||||
R_TRY(ActivateContentMetaDatabase(StorageId::BuiltInSystem));
|
||||
|
||||
R_TRY(impl::ActivateContentMetaDatabase(StorageId::BuiltInSystem));
|
||||
|
||||
/* Now for BuiltInUser's content storage and content meta entries. */
|
||||
g_content_storage_roots[g_num_content_storage_entries++].Initialize(StorageId::BuiltInUser, FsContentStorageId_User);
|
||||
|
@ -316,12 +316,12 @@ namespace ams::ncm::impl {
|
|||
|
||||
for (size_t i = 0; i < MaxContentStorageEntries; i++) {
|
||||
ContentStorageRoot *entry = &g_content_storage_roots[i];
|
||||
InactivateContentStorage(entry->storage_id);
|
||||
impl::InactivateContentStorage(entry->storage_id);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < MaxContentMetaDatabaseEntries; i++) {
|
||||
ContentMetaDatabaseEntry *entry = &g_content_meta_entries[i];
|
||||
InactivateContentMetaDatabase(entry->storage_id);
|
||||
impl::InactivateContentMetaDatabase(entry->storage_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,7 @@ namespace ams::ncm::impl {
|
|||
|
||||
ContentStorageRoot *root;
|
||||
R_TRY(GetUniqueContentStorageRoot(std::addressof(root), storage_id));
|
||||
|
||||
|
||||
auto content_storage = root->content_storage;
|
||||
|
||||
if (hos::GetVersion() >= hos::Version_200) {
|
||||
|
@ -382,7 +382,7 @@ namespace ams::ncm::impl {
|
|||
} else {
|
||||
/* 1.0.0 activates content storages as soon as they are opened. */
|
||||
if (!content_storage) {
|
||||
R_TRY(ActivateContentStorage(storage_id));
|
||||
R_TRY(impl::ActivateContentStorage(storage_id));
|
||||
content_storage = root->content_storage;
|
||||
}
|
||||
}
|
||||
|
@ -518,7 +518,7 @@ namespace ams::ncm::impl {
|
|||
|
||||
ContentMetaDatabaseEntry *entry;
|
||||
R_TRY(GetUniqueContentMetaDatabaseEntry(&entry, storage_id));
|
||||
|
||||
|
||||
auto content_meta_db = entry->content_meta_database;
|
||||
|
||||
if (hos::GetVersion() >= hos::Version_200) {
|
||||
|
@ -526,7 +526,7 @@ namespace ams::ncm::impl {
|
|||
} else {
|
||||
/* 1.0.0 activates content meta databases as soon as they are opened. */
|
||||
if (!content_meta_db) {
|
||||
R_TRY(ActivateContentMetaDatabase(storage_id));
|
||||
R_TRY(impl::ActivateContentMetaDatabase(storage_id));
|
||||
content_meta_db = entry->content_meta_database;
|
||||
}
|
||||
}
|
||||
|
@ -541,7 +541,7 @@ namespace ams::ncm::impl {
|
|||
R_UNLESS(storage_id != StorageId::None, ncm::ResultUnknownStorage());
|
||||
ContentMetaDatabaseEntry *entry;
|
||||
R_TRY(FindContentMetaDatabaseEntry(&entry, storage_id));
|
||||
|
||||
|
||||
auto content_meta_db = entry->content_meta_database;
|
||||
|
||||
if (content_meta_db) {
|
||||
|
|
|
@ -14,70 +14,70 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ncm_content_manager_impl.hpp"
|
||||
#include "impl/ncm_content_manager.hpp"
|
||||
#include "ncm_content_manager_service.hpp"
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
Result ContentManagerService::CreateContentStorage(StorageId storage_id) {
|
||||
Result ContentManagerImpl::CreateContentStorage(StorageId storage_id) {
|
||||
return impl::CreateContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) {
|
||||
Result ContentManagerImpl::CreateContentMetaDatabase(StorageId storage_id) {
|
||||
return impl::CreateContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::VerifyContentStorage(StorageId storage_id) {
|
||||
Result ContentManagerImpl::VerifyContentStorage(StorageId storage_id) {
|
||||
return impl::VerifyContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) {
|
||||
Result ContentManagerImpl::VerifyContentMetaDatabase(StorageId storage_id) {
|
||||
return impl::VerifyContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id) {
|
||||
Result ContentManagerImpl::OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id) {
|
||||
std::shared_ptr<IContentStorage> content_storage;
|
||||
R_TRY(impl::OpenContentStorage(&content_storage, storage_id));
|
||||
out.SetValue(std::move(content_storage));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentManagerService::OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id) {
|
||||
Result ContentManagerImpl::OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id) {
|
||||
std::shared_ptr<IContentMetaDatabase> content_meta_database;
|
||||
R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id));
|
||||
out.SetValue(std::move(content_meta_database));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) {
|
||||
Result ContentManagerImpl::CloseContentStorageForcibly(StorageId storage_id) {
|
||||
return impl::CloseContentStorageForcibly(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) {
|
||||
Result ContentManagerImpl::CloseContentMetaDatabaseForcibly(StorageId storage_id) {
|
||||
return impl::CloseContentMetaDatabaseForcibly(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) {
|
||||
Result ContentManagerImpl::CleanupContentMetaDatabase(StorageId storage_id) {
|
||||
return impl::CleanupContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::ActivateContentStorage(StorageId storage_id) {
|
||||
Result ContentManagerImpl::ActivateContentStorage(StorageId storage_id) {
|
||||
return impl::ActivateContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::InactivateContentStorage(StorageId storage_id) {
|
||||
Result ContentManagerImpl::InactivateContentStorage(StorageId storage_id) {
|
||||
return impl::InactivateContentStorage(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) {
|
||||
Result ContentManagerImpl::ActivateContentMetaDatabase(StorageId storage_id) {
|
||||
return impl::ActivateContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) {
|
||||
Result ContentManagerImpl::InactivateContentMetaDatabase(StorageId storage_id) {
|
||||
return impl::InactivateContentMetaDatabase(storage_id);
|
||||
}
|
||||
|
||||
Result ContentManagerService::InvalidateRightsIdCache() {
|
||||
Result ContentManagerImpl::InvalidateRightsIdCache() {
|
||||
return impl::InvalidateRightsIdCache();
|
||||
}
|
||||
|
40
stratosphere/ncm/source/ncm_content_manager_impl.hpp
Normal file
40
stratosphere/ncm/source/ncm_content_manager_impl.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 ContentManagerImpl final : public IContentManager {
|
||||
public:
|
||||
virtual Result CreateContentStorage(StorageId storage_id) override;
|
||||
virtual Result CreateContentMetaDatabase(StorageId storage_id) override;
|
||||
virtual Result VerifyContentStorage(StorageId storage_id) override;
|
||||
virtual Result VerifyContentMetaDatabase(StorageId storage_id) override;
|
||||
virtual Result OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id) override;
|
||||
virtual Result OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id) override;
|
||||
virtual Result CloseContentStorageForcibly(StorageId storage_id) override;
|
||||
virtual Result CloseContentMetaDatabaseForcibly(StorageId storage_id) override;
|
||||
virtual Result CleanupContentMetaDatabase(StorageId storage_id) override;
|
||||
virtual Result ActivateContentStorage(StorageId storage_id) override;
|
||||
virtual Result InactivateContentStorage(StorageId storage_id) override;
|
||||
virtual Result ActivateContentMetaDatabase(StorageId storage_id) override;
|
||||
virtual Result InactivateContentMetaDatabase(StorageId storage_id) override;
|
||||
virtual Result InvalidateRightsIdCache() override;
|
||||
};
|
||||
|
||||
}
|
|
@ -297,7 +297,7 @@ namespace ams::ncm {
|
|||
return fsdevCommitDevice(this->mount_name);
|
||||
}
|
||||
|
||||
Result ContentMetaDatabaseImpl::HasContent(sf::Out<bool> out, const ContentMetaKey &key, ContentId content_id) {
|
||||
Result ContentMetaDatabaseImpl::HasContent(sf::Out<bool> out, const ContentMetaKey &key, const ContentId &content_id) {
|
||||
const void *meta;
|
||||
size_t meta_size;
|
||||
R_TRY(this->GetContentMetaPointer(&meta, &meta_size, key));
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace ams::ncm {
|
|||
virtual Result DisableForcibly() override;
|
||||
virtual Result LookupOrphanContent(const sf::OutArray<bool> &out_orphaned, const sf::InArray<ContentId> &content_ids) override;
|
||||
virtual Result Commit() override;
|
||||
virtual Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, ContentId content_id) override;
|
||||
virtual Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, const ContentId &content_id) override;
|
||||
virtual Result ListContentMetaInfo(sf::Out<u32> out_entries_written, const sf::OutArray<ContentMetaInfo> &out_meta_info, const ContentMetaKey &key, u32 start_index) override;
|
||||
virtual Result GetAttributes(sf::Out<ContentMetaAttribute> out_attributes, const ContentMetaKey &key) override;
|
||||
virtual Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key) override;
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace ams::ncm {
|
|||
|
||||
char placeholder_path[FS_MAX_PATH] = {0};
|
||||
this->placeholder_accessor.MakePath(placeholder_path, placeholder_id);
|
||||
|
||||
|
||||
bool has = false;
|
||||
R_TRY(fs::HasFile(&has, placeholder_path));
|
||||
out.SetValue(has);
|
||||
|
@ -173,25 +173,25 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentStorageImpl::GetPath(sf::Out<lr::Path> out, ContentId content_id) {
|
||||
Result ContentStorageImpl::GetPath(sf::Out<Path> out, ContentId content_id) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
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));
|
||||
out.SetValue(lr::Path::Encode(common_path));
|
||||
out.SetValue(Path::Encode(common_path));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentStorageImpl::GetPlaceHolderPath(sf::Out<lr::Path> out, PlaceHolderId placeholder_id) {
|
||||
Result ContentStorageImpl::GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
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));
|
||||
out.SetValue(lr::Path::Encode(common_path));
|
||||
out.SetValue(Path::Encode(common_path));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ namespace ams::ncm {
|
|||
this->placeholder_accessor.InvalidateAll();
|
||||
this->placeholder_accessor.MakeRootPath(placeholder_root_path);
|
||||
|
||||
/* Nintendo uses CleanDirectoryRecursively which is 3.0.0+.
|
||||
/* Nintendo uses CleanDirectoryRecursively which is 3.0.0+.
|
||||
We'll just delete the directory and recreate it to support all firmwares. */
|
||||
R_TRY(fsdevDeleteDirectoryRecursively(placeholder_root_path));
|
||||
R_UNLESS(mkdir(placeholder_root_path, S_IRWXU) != -1, fsdevGetLastResult());
|
||||
|
@ -220,15 +220,15 @@ namespace ams::ncm {
|
|||
R_TRY(fs::TraverseDirectory(placeholder_root_path, dir_depth, [&](bool *should_continue, bool *should_retry_dir_read, const char *current_path, struct dirent *dir_entry) -> Result {
|
||||
*should_continue = true;
|
||||
*should_retry_dir_read = false;
|
||||
|
||||
|
||||
if (dir_entry->d_type == DT_REG) {
|
||||
R_UNLESS(entry_count <= out_buf.GetSize(), ncm::ResultBufferInsufficient());
|
||||
|
||||
|
||||
PlaceHolderId cur_entry_placeholder_id = {0};
|
||||
R_TRY(GetPlaceHolderIdFromDirEntry(&cur_entry_placeholder_id, dir_entry));
|
||||
out_buf[entry_count++] = cur_entry_placeholder_id;
|
||||
}
|
||||
|
||||
|
||||
return ResultSuccess();
|
||||
}));
|
||||
|
||||
|
@ -329,7 +329,7 @@ namespace ams::ncm {
|
|||
|
||||
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};
|
||||
char new_content_path[FS_MAX_PATH] = {0};
|
||||
char placeholder_path[FS_MAX_PATH] = {0};
|
||||
|
@ -401,7 +401,7 @@ namespace ams::ncm {
|
|||
|
||||
Result ContentStorageImpl::GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
|
||||
if (this->rights_id_cache->Find(out_rights_id.GetPointer(), content_id)) {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
@ -437,7 +437,7 @@ namespace ams::ncm {
|
|||
|
||||
FILE *f = nullptr;
|
||||
R_TRY(fs::OpenFile(&f, content_path, FsOpenMode_Write));
|
||||
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
fclose(f);
|
||||
};
|
||||
|
@ -522,7 +522,7 @@ namespace ams::ncm {
|
|||
|
||||
Result ContentStorageImpl::GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
|
||||
if (this->rights_id_cache->Find(out_rights_id.GetPointer(), cache_content_id)) {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
|
|
@ -60,8 +60,8 @@ namespace ams::ncm {
|
|||
virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) override;
|
||||
virtual Result Delete(ContentId content_id) override;
|
||||
virtual Result Has(sf::Out<bool> out, ContentId content_id) override;
|
||||
virtual Result GetPath(sf::Out<lr::Path> out, ContentId content_id) override;
|
||||
virtual Result GetPlaceHolderPath(sf::Out<lr::Path> out, PlaceHolderId placeholder_id) override;
|
||||
virtual Result GetPath(sf::Out<Path> out, ContentId content_id) override;
|
||||
virtual Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id) override;
|
||||
virtual Result CleanupAllPlaceHolder() override;
|
||||
virtual Result ListPlaceHolder(sf::Out<u32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) override;
|
||||
virtual Result GetContentCount(sf::Out<u32> out_count) override;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <stratosphere/lr/lr_location_resolver_manager_impl.hpp>
|
||||
|
||||
#include "impl/ncm_content_manager.hpp"
|
||||
#include "ncm_content_manager_service.hpp"
|
||||
#include "ncm_content_manager_impl.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
@ -100,6 +100,39 @@ namespace {
|
|||
|
||||
constexpr inline sm::ServiceName ContentManagerServiceName = sm::ServiceName::Encode("ncm");
|
||||
|
||||
class ContentManagerServerManager : public sf::hipc::ServerManager<ContentManagerNumServers, ContentManagerServerOptions, ContentManagerMaxSessions> {
|
||||
private:
|
||||
static constexpr size_t ThreadStackSize = 0x4000;
|
||||
static constexpr int ThreadPriority = 0x15;
|
||||
|
||||
using ServiceType = ncm::ContentManagerImpl;
|
||||
private:
|
||||
os::StaticThread<ThreadStackSize> thread;
|
||||
std::shared_ptr<ServiceType> ncm_manager;
|
||||
private:
|
||||
static void ThreadFunction(void *_this) {
|
||||
reinterpret_cast<ContentManagerServerManager *>(_this)->LoopProcess();
|
||||
}
|
||||
public:
|
||||
ContentManagerServerManager(ServiceType *m)
|
||||
: thread(ThreadFunction, this, ThreadPriority), ncm_manager(sf::ServiceObjectTraits<ServiceType>::SharedPointerHelper::GetEmptyDeleteSharedPointer(m))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
ams::Result Initialize() {
|
||||
return this->RegisterServer<ServiceType>(ContentManagerServiceName, ContentManagerManagerSessions, this->ncm_manager);
|
||||
}
|
||||
|
||||
ams::Result StartThreads() {
|
||||
return this->thread.Start();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
this->thread.Join();
|
||||
}
|
||||
};
|
||||
|
||||
struct LocationResolverServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
|
@ -146,7 +179,8 @@ namespace {
|
|||
}
|
||||
};
|
||||
|
||||
sf::hipc::ServerManager<ContentManagerNumServers, ContentManagerServerOptions, ContentManagerMaxSessions> g_ncm_server_manager;
|
||||
ncm::ContentManagerImpl g_ncm_manager_service_object;
|
||||
ContentManagerServerManager g_ncm_server_manager(std::addressof(g_ncm_manager_service_object));
|
||||
|
||||
lr::LocationResolverManagerImpl g_lr_manager_service_object;
|
||||
LocationResolverServerManager g_lr_server_manager(std::addressof(g_lr_manager_service_object));
|
||||
|
@ -155,7 +189,7 @@ namespace {
|
|||
|
||||
void ContentManagerServerMain(void *arg) {
|
||||
/* Create services. */
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.RegisterServer<ncm::ContentManagerService>(ContentManagerServiceName, ContentManagerManagerSessions));
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.RegisterServer<ncm::ContentManagerImpl>(ContentManagerServiceName, ContentManagerManagerSessions));
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
g_ncm_server_manager.LoopProcess();
|
||||
|
@ -164,19 +198,19 @@ void ContentManagerServerMain(void *arg) {
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Initialize content manager implementation. */
|
||||
/* TODO: Move Initialize/Finalize into ContentManagerImpl ctor/dtor, initialize client library with static object. */
|
||||
R_ABORT_UNLESS(ams::ncm::impl::InitializeContentManager());
|
||||
|
||||
static os::Thread s_content_manager_thread;
|
||||
|
||||
R_ABORT_UNLESS(s_content_manager_thread.Initialize(&ContentManagerServerMain, nullptr, 0x4000, 0x15));
|
||||
R_ABORT_UNLESS(s_content_manager_thread.Start());
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.Initialize());
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.StartThreads());
|
||||
|
||||
R_ABORT_UNLESS(g_lr_server_manager.Initialize());
|
||||
R_ABORT_UNLESS(g_lr_server_manager.StartThreads());
|
||||
|
||||
s_content_manager_thread.Join();
|
||||
g_ncm_server_manager.Wait();
|
||||
g_lr_server_manager.Wait();
|
||||
|
||||
/* TODO: This call is eventually automatic at scope exit. */
|
||||
ams::ncm::impl::FinalizeContentManager();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace ams::ncm {
|
|||
|
||||
bool has = false;
|
||||
R_TRY(fs::HasFile(&has, content_path));
|
||||
|
||||
|
||||
if (!has) {
|
||||
path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path);
|
||||
R_TRY(fs::HasFile(&has, content_path));
|
||||
|
@ -76,7 +76,7 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageImpl::GetPath(sf::Out<lr::Path> out, ContentId content_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetPath(sf::Out<Path> out, ContentId content_id) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
char content_path[FS_MAX_PATH] = {0};
|
||||
|
@ -85,18 +85,18 @@ namespace ams::ncm {
|
|||
|
||||
path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path);
|
||||
R_TRY(fs::HasFile(&is_content_meta_file, content_path));
|
||||
|
||||
|
||||
if (!is_content_meta_file) {
|
||||
this->make_content_path_func(content_path, content_id, this->root_path);
|
||||
}
|
||||
|
||||
|
||||
R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path));
|
||||
out.SetValue(lr::Path::Encode(common_path));
|
||||
out.SetValue(Path::Encode(common_path));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ReadOnlyContentStorageImpl::GetPlaceHolderPath(sf::Out<lr::Path> out, PlaceHolderId placeholder_id) {
|
||||
Result ReadOnlyContentStorageImpl::GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id) {
|
||||
return ResultInvalidContentStorageOperation();
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ namespace ams::ncm {
|
|||
|
||||
this->make_content_path_func(content_path, content_id, this->root_path);
|
||||
R_TRY(fs::HasFile(&is_content_file, content_path));
|
||||
|
||||
|
||||
if (!is_content_file) {
|
||||
path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path);
|
||||
}
|
||||
|
@ -158,18 +158,18 @@ namespace ams::ncm {
|
|||
|
||||
this->make_content_path_func(content_path, content_id, this->root_path);
|
||||
R_TRY(fs::HasFile(&is_content_file, content_path));
|
||||
|
||||
|
||||
if (!is_content_file) {
|
||||
path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path);
|
||||
}
|
||||
|
||||
|
||||
FILE *f = nullptr;
|
||||
R_TRY(fs::OpenFile(&f, content_path, FsOpenMode_Read));
|
||||
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
fclose(f);
|
||||
};
|
||||
|
||||
|
||||
R_TRY(fs::ReadFile(f, offset, buf.GetPointer(), buf.GetSize()));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
@ -198,13 +198,13 @@ namespace ams::ncm {
|
|||
|
||||
path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path);
|
||||
R_TRY(fs::HasFile(&is_content_meta_file, content_path));
|
||||
|
||||
|
||||
if (!is_content_meta_file) {
|
||||
this->make_content_path_func(content_path, content_id, this->root_path);
|
||||
}
|
||||
|
||||
R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path));
|
||||
|
||||
|
||||
ncm::RightsId rights_id;
|
||||
R_TRY(GetRightsId(&rights_id, common_path));
|
||||
out_rights_id.SetValue(rights_id);
|
||||
|
|
|
@ -33,8 +33,8 @@ namespace ams::ncm {
|
|||
virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) override;
|
||||
virtual Result Delete(ContentId content_id) override;
|
||||
virtual Result Has(sf::Out<bool> out, ContentId content_id) override;
|
||||
virtual Result GetPath(sf::Out<lr::Path> out, ContentId content_id) override;
|
||||
virtual Result GetPlaceHolderPath(sf::Out<lr::Path> out, PlaceHolderId placeholder_id) override;
|
||||
virtual Result GetPath(sf::Out<Path> out, ContentId content_id) override;
|
||||
virtual Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id) override;
|
||||
virtual Result CleanupAllPlaceHolder() override;
|
||||
virtual Result ListPlaceHolder(sf::Out<u32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) override;
|
||||
virtual Result GetContentCount(sf::Out<u32> out_count) override;
|
||||
|
|
Loading…
Add table
Reference in a new issue