mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
sprofile: update for 14.0.0 (orphaned profiles now deleted on import)
This commit is contained in:
parent
9acf48ba5f
commit
40601cc74c
22 changed files with 320 additions and 112 deletions
|
@ -21,7 +21,7 @@ namespace ams::fs::impl {
|
||||||
#define ADD_ENUM_CASE(v) case v: return #v
|
#define ADD_ENUM_CASE(v) case v: return #v
|
||||||
|
|
||||||
template<> const char *IdString::ToString<pkg1::KeyGeneration>(pkg1::KeyGeneration id) {
|
template<> const char *IdString::ToString<pkg1::KeyGeneration>(pkg1::KeyGeneration id) {
|
||||||
static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_13_0_0);
|
static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_14_0_0);
|
||||||
switch (id) {
|
switch (id) {
|
||||||
using enum pkg1::KeyGeneration;
|
using enum pkg1::KeyGeneration;
|
||||||
case KeyGeneration_1_0_0: return "1.0.0-2.3.0";
|
case KeyGeneration_1_0_0: return "1.0.0-2.3.0";
|
||||||
|
@ -36,7 +36,8 @@ namespace ams::fs::impl {
|
||||||
case KeyGeneration_9_0_0: return "9.0.0-9.0.1";
|
case KeyGeneration_9_0_0: return "9.0.0-9.0.1";
|
||||||
case KeyGeneration_9_1_0: return "9.1.0-12.0.3";
|
case KeyGeneration_9_1_0: return "9.1.0-12.0.3";
|
||||||
case KeyGeneration_12_1_0: return "12.1.0";
|
case KeyGeneration_12_1_0: return "12.1.0";
|
||||||
case KeyGeneration_13_0_0: return "13.0.0-";
|
case KeyGeneration_13_0_0: return "13.0.0-13.2.1";
|
||||||
|
case KeyGeneration_14_0_0: return "14.0.0-";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "sprofile_srv_profile_manager.hpp"
|
#include "sprofile_srv_profile_manager.hpp"
|
||||||
#include "sprofile_srv_service_for_bg_agent.hpp"
|
#include "sprofile_srv_service_for_bg_agent.hpp"
|
||||||
#include "sprofile_srv_service_for_system_process.hpp"
|
#include "sprofile_srv_service_for_system_process.hpp"
|
||||||
|
#include "sprofile_srv_service_getter.hpp"
|
||||||
|
|
||||||
namespace ams::sprofile::srv {
|
namespace ams::sprofile::srv {
|
||||||
|
|
||||||
|
@ -55,6 +56,9 @@ namespace ams::sprofile::srv {
|
||||||
constinit util::TypedStorage<sf::UnmanagedServiceObject<ISprofileServiceForBgAgent, ServiceForBgAgent>> g_bg_service_object = {};
|
constinit util::TypedStorage<sf::UnmanagedServiceObject<ISprofileServiceForBgAgent, ServiceForBgAgent>> g_bg_service_object = {};
|
||||||
constinit util::TypedStorage<sf::UnmanagedServiceObject<ISprofileServiceForSystemProcess, ServiceForSystemProcess>> g_sp_service_object = {};
|
constinit util::TypedStorage<sf::UnmanagedServiceObject<ISprofileServiceForSystemProcess, ServiceForSystemProcess>> g_sp_service_object = {};
|
||||||
|
|
||||||
|
constinit util::TypedStorage<sf::UnmanagedServiceObject<IServiceGetter, ServiceGetter>> g_bg_service_getter = {};
|
||||||
|
constinit util::TypedStorage<sf::UnmanagedServiceObject<IServiceGetter, ServiceGetter>> g_sp_service_getter = {};
|
||||||
|
|
||||||
constinit util::TypedStorage<ServerManager> g_server_manager = {};
|
constinit util::TypedStorage<ServerManager> g_server_manager = {};
|
||||||
|
|
||||||
alignas(os::ThreadStackAlignment) constinit u8 g_ipc_thread_stack[0x3000];
|
alignas(os::ThreadStackAlignment) constinit u8 g_ipc_thread_stack[0x3000];
|
||||||
|
@ -95,13 +99,22 @@ namespace ams::sprofile::srv {
|
||||||
util::ConstructAt(g_bg_service_object, std::addressof(g_sf_memory_resource), util::GetPointer(g_profile_manager));
|
util::ConstructAt(g_bg_service_object, std::addressof(g_sf_memory_resource), util::GetPointer(g_profile_manager));
|
||||||
util::ConstructAt(g_sp_service_object, std::addressof(g_sf_memory_resource), util::GetPointer(g_profile_manager));
|
util::ConstructAt(g_sp_service_object, std::addressof(g_sf_memory_resource), util::GetPointer(g_profile_manager));
|
||||||
|
|
||||||
|
/* Create the service getters. */
|
||||||
|
util::ConstructAt(g_bg_service_getter, util::GetReference(g_bg_service_object).GetShared(), util::GetReference(g_sp_service_object).GetShared());
|
||||||
|
util::ConstructAt(g_sp_service_getter, nullptr, util::GetReference(g_sp_service_object).GetShared());
|
||||||
|
|
||||||
/* Create the server manager. */
|
/* Create the server manager. */
|
||||||
util::ConstructAt(g_server_manager);
|
util::ConstructAt(g_server_manager);
|
||||||
|
|
||||||
/* Create services. */
|
/* Create services. */
|
||||||
|
if (hos::GetVersion() >= hos::Version_14_0_0) {
|
||||||
|
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_bg_service_getter).GetShared(), ServiceNameForBgAgent, BgAgentSessionCountMax));
|
||||||
|
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_sp_service_getter).GetShared(), ServiceNameForSystemProcess, SystemProcessSessionCountMax));
|
||||||
|
} else {
|
||||||
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_bg_service_object).GetShared(), ServiceNameForBgAgent, BgAgentSessionCountMax));
|
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_bg_service_object).GetShared(), ServiceNameForBgAgent, BgAgentSessionCountMax));
|
||||||
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_sp_service_object).GetShared(), ServiceNameForSystemProcess, SystemProcessSessionCountMax));
|
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_sp_service_object).GetShared(), ServiceNameForSystemProcess, SystemProcessSessionCountMax));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StartIpcServer() {
|
void StartIpcServer() {
|
||||||
/* Create the ipc server thread. */
|
/* Create the ipc server thread. */
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace ams::sprofile::srv {
|
||||||
/* Check the size was correct. */
|
/* Check the size was correct. */
|
||||||
AMS_ABORT_UNLESS(size == read_size);
|
AMS_ABORT_UNLESS(size == read_size);
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result WriteFile(const char *path, const void *src, size_t size) {
|
Result WriteFile(const char *path, const void *src, size_t size) {
|
||||||
|
@ -51,7 +51,7 @@ namespace ams::sprofile::srv {
|
||||||
R_ABORT_UNLESS(fs::SetFileSize(file, size));
|
R_ABORT_UNLESS(fs::SetFileSize(file, size));
|
||||||
|
|
||||||
/* Write the file. */
|
/* Write the file. */
|
||||||
return fs::WriteFile(file, 0, src, size, fs::WriteOption::Flush);
|
R_RETURN(fs::WriteFile(file, 0, src, size, fs::WriteOption::Flush));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MoveFile(const char *src_path, const char *dst_path) {
|
Result MoveFile(const char *src_path, const char *dst_path) {
|
||||||
|
@ -70,7 +70,15 @@ namespace ams::sprofile::srv {
|
||||||
/* Move the source file to the destination file. */
|
/* Move the source file to the destination file. */
|
||||||
R_TRY(fs::RenameFile(src_path, dst_path));
|
R_TRY(fs::RenameFile(src_path, dst_path));
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DeleteFile(const char *path) {
|
||||||
|
R_TRY_CATCH(fs::DeleteFile(path)) {
|
||||||
|
R_CATCH(fs::ResultPathNotFound) { /* It's okay if the file doesn't exist. */ }
|
||||||
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result EnsureDirectory(const char *path) {
|
Result EnsureDirectory(const char *path) {
|
||||||
|
@ -78,7 +86,7 @@ namespace ams::sprofile::srv {
|
||||||
R_CATCH(fs::ResultPathAlreadyExists) { /* It's okay if the directory already exists. */ }
|
R_CATCH(fs::ResultPathAlreadyExists) { /* It's okay if the directory already exists. */ }
|
||||||
} R_END_TRY_CATCH;
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace ams::sprofile::srv {
|
||||||
Result ReadFile(const char *path, void *dst, size_t size, s64 offset);
|
Result ReadFile(const char *path, void *dst, size_t size, s64 offset);
|
||||||
Result WriteFile(const char *path, const void *src, size_t size);
|
Result WriteFile(const char *path, const void *src, size_t size);
|
||||||
Result MoveFile(const char *src_path, const char *dst_path);
|
Result MoveFile(const char *src_path, const char *dst_path);
|
||||||
|
Result DeleteFile(const char *path);
|
||||||
|
|
||||||
Result EnsureDirectory(const char *path);
|
Result EnsureDirectory(const char *path);
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,4 @@
|
||||||
AMS_SF_METHOD_INFO(C, H, 2001, Result, GetRaw, (sf::Out<u8> out_type, sf::Out<u64> out_value, sprofile::Identifier profile, sprofile::Identifier key), (out_type, out_value, profile, key))
|
AMS_SF_METHOD_INFO(C, H, 2001, Result, GetRaw, (sf::Out<u8> out_type, sf::Out<u64> out_value, sprofile::Identifier profile, sprofile::Identifier key), (out_type, out_value, profile, key))
|
||||||
|
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::sprofile, IProfileControllerForDebug, AMS_SPROFILE_I_PROFILE_CONTROLLER_FOR_DEBUG_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileControllerForDebug, AMS_SPROFILE_I_PROFILE_CONTROLLER_FOR_DEBUG_INTERFACE_INFO)
|
||||||
|
|
|
@ -22,4 +22,4 @@
|
||||||
AMS_SF_METHOD_INFO(C, H, 1, Result, Commit, (), ()) \
|
AMS_SF_METHOD_INFO(C, H, 1, Result, Commit, (), ()) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 2, Result, ImportMetadata, (const sprofile::srv::ProfileMetadataForImportMetadata &import), (import)) \
|
AMS_SF_METHOD_INFO(C, H, 2, Result, ImportMetadata, (const sprofile::srv::ProfileMetadataForImportMetadata &import), (import)) \
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::sprofile, IProfileImporter, AMS_SPROFILE_I_PROFILE_IMPORTER_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileImporter, AMS_SPROFILE_I_PROFILE_IMPORTER_INTERFACE_INFO)
|
||||||
|
|
|
@ -23,4 +23,4 @@
|
||||||
AMS_SF_METHOD_INFO(C, H, 3, Result, GetUnsigned32, (sf::Out<u32> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \
|
AMS_SF_METHOD_INFO(C, H, 3, Result, GetUnsigned32, (sf::Out<u32> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 4, Result, GetByte, (sf::Out<u8> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key))
|
AMS_SF_METHOD_INFO(C, H, 4, Result, GetByte, (sf::Out<u8> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key))
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::sprofile, IProfileReader, AMS_SPROFILE_I_PROFILE_READER_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileReader, AMS_SPROFILE_I_PROFILE_READER_INTERFACE_INFO)
|
||||||
|
|
|
@ -21,4 +21,4 @@
|
||||||
AMS_SF_METHOD_INFO(C, H, 1, Result, Unlisten, (sprofile::Identifier profile), (profile)) \
|
AMS_SF_METHOD_INFO(C, H, 1, Result, Unlisten, (sprofile::Identifier profile), (profile)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 2, Result, GetEventHandle, (ams::sf::OutCopyHandle out), (out))
|
AMS_SF_METHOD_INFO(C, H, 2, Result, GetEventHandle, (ams::sf::OutCopyHandle out), (out))
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::sprofile, IProfileUpdateObserver, AMS_SPROFILE_I_PROFILE_UPDATE_OBSERVER_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileUpdateObserver, AMS_SPROFILE_I_PROFILE_UPDATE_OBSERVER_INTERFACE_INFO)
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
#include "sprofile_srv_i_profile_importer.hpp"
|
#include "sprofile_srv_i_profile_importer.hpp"
|
||||||
|
|
||||||
#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO(C, H) \
|
#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileImporter, (sf::Out<sf::SharedPointer<::ams::sprofile::IProfileImporter>> out), (out)) \
|
AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileImporter, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileImporter>> out), (out)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 200, Result, GetImportableProfileUrls, (sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \
|
AMS_SF_METHOD_INFO(C, H, 200, Result, GetImportableProfileUrls, (sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out<bool> out, sprofile::Identifier revision_key), (out, revision_key)) \
|
AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out<bool> out, sprofile::Identifier revision_key), (out, revision_key)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ())
|
AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ())
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::sprofile, ISprofileServiceForBgAgent, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, ISprofileServiceForBgAgent, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO)
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
#include "sprofile_srv_i_profile_controller_for_debug.hpp"
|
#include "sprofile_srv_i_profile_controller_for_debug.hpp"
|
||||||
|
|
||||||
#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_SYSTEM_PROCESS_INTERFACE_INFO(C, H) \
|
#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_SYSTEM_PROCESS_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileReader, (sf::Out<sf::SharedPointer<::ams::sprofile::IProfileReader>> out), (out)) \
|
AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileReader, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileReader>> out), (out)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 101, Result, OpenProfileUpdateObserver, (sf::Out<sf::SharedPointer<::ams::sprofile::IProfileUpdateObserver>> out), (out)) \
|
AMS_SF_METHOD_INFO(C, H, 101, Result, OpenProfileUpdateObserver, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> out), (out)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 900, Result, OpenProfileControllerForDebug, (sf::Out<sf::SharedPointer<::ams::sprofile::IProfileControllerForDebug>> out), (out))
|
AMS_SF_METHOD_INFO(C, H, 900, Result, OpenProfileControllerForDebug, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileControllerForDebug>> out), (out))
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::sprofile, ISprofileServiceForSystemProcess, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_SYSTEM_PROCESS_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, ISprofileServiceForSystemProcess, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_SYSTEM_PROCESS_INTERFACE_INFO)
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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 "sprofile_srv_i_service_for_system_process.hpp"
|
||||||
|
#include "sprofile_srv_i_service_for_bg_agent.hpp"
|
||||||
|
|
||||||
|
#define AMS_SPROFILE_I_SERVICE_GETTER_INTERFACE_INFO(C, H) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 0, Result, GetServiceForSystemProcess, (sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForSystemProcess>> out), (out)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 1, Result, GetServiceForBgAgent, (sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForBgAgent>> out), (out))
|
||||||
|
|
||||||
|
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IServiceGetter, AMS_SPROFILE_I_SERVICE_GETTER_INTERFACE_INFO)
|
|
@ -20,16 +20,22 @@
|
||||||
namespace ams::sprofile::srv {
|
namespace ams::sprofile::srv {
|
||||||
|
|
||||||
class ProfileImporter {
|
class ProfileImporter {
|
||||||
|
private:
|
||||||
|
struct ImportingProfile {
|
||||||
|
Identifier identifier_0;
|
||||||
|
Identifier identifier_1;
|
||||||
|
bool is_new_import;
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
bool m_committed;
|
bool m_committed;
|
||||||
bool m_imported_metadata;
|
bool m_imported_metadata;
|
||||||
int m_importing_count;
|
int m_importing_count;
|
||||||
util::optional<ProfileMetadata> m_metadata;
|
util::optional<ProfileMetadata> m_metadata;
|
||||||
Identifier m_importing_profiles[50];
|
ImportingProfile m_importing_profiles[50];
|
||||||
util::BitFlagSet<50> m_imported_profiles;
|
util::BitFlagSet<50> m_is_profile_importable;
|
||||||
Identifier m_revision_key;
|
Identifier m_revision_key;
|
||||||
public:
|
public:
|
||||||
ProfileImporter(const util::optional<ProfileMetadata> &meta) : m_committed(false), m_imported_metadata(false), m_importing_count(0), m_metadata(util::nullopt), m_imported_profiles(), m_revision_key() {
|
ProfileImporter(const util::optional<ProfileMetadata> &meta) : m_committed(false), m_imported_metadata(false), m_importing_count(0), m_metadata(util::nullopt), m_is_profile_importable(), m_revision_key() {
|
||||||
if (meta.has_value()) {
|
if (meta.has_value()) {
|
||||||
m_metadata = *meta;
|
m_metadata = *meta;
|
||||||
}
|
}
|
||||||
|
@ -62,12 +68,23 @@ namespace ams::sprofile::srv {
|
||||||
/* Import the service revision key. */
|
/* Import the service revision key. */
|
||||||
m_revision_key = meta.revision_key;
|
m_revision_key = meta.revision_key;
|
||||||
|
|
||||||
/* Import all profiles. */
|
/* Set all profiles as importable. */
|
||||||
|
for (auto i = 0u; i < std::min<size_t>(meta.num_entries, util::size(meta.entries)); ++i) {
|
||||||
|
m_is_profile_importable[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine import status for all profiles. */
|
||||||
for (auto i = 0u; i < std::min<size_t>(meta.num_entries, util::size(meta.entries)); ++i) {
|
for (auto i = 0u; i < std::min<size_t>(meta.num_entries, util::size(meta.entries)); ++i) {
|
||||||
const auto &import_entry = meta.entries[i];
|
const auto &import_entry = meta.entries[i];
|
||||||
if (!this->HasProfile(import_entry.identifier_0, import_entry.identifier_1)) {
|
|
||||||
m_importing_profiles[m_importing_count++] = import_entry.identifier_0;
|
const bool is_new_import = !this->HasProfile(import_entry.identifier_0, import_entry.identifier_1);
|
||||||
}
|
|
||||||
|
m_importing_profiles[i] = {
|
||||||
|
.identifier_0 = import_entry.identifier_0,
|
||||||
|
.identifier_1 = import_entry.identifier_1,
|
||||||
|
.is_new_import = is_new_import,
|
||||||
|
};
|
||||||
|
m_is_profile_importable[i] = is_new_import;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +93,9 @@ namespace ams::sprofile::srv {
|
||||||
if (m_imported_metadata) {
|
if (m_imported_metadata) {
|
||||||
/* Find the specified profile. */
|
/* Find the specified profile. */
|
||||||
for (auto i = 0; i < m_importing_count; ++i) {
|
for (auto i = 0; i < m_importing_count; ++i) {
|
||||||
if (m_importing_profiles[i] == profile) {
|
if (m_importing_profiles[i].identifier_0 == profile) {
|
||||||
/* Require the profile not already be imported. */
|
/* Require the profile be importable. */
|
||||||
return !m_imported_profiles[i];
|
return m_is_profile_importable[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,10 +105,10 @@ namespace ams::sprofile::srv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnImportProfile(Identifier profile) {
|
void OnImportProfile(Identifier profile) {
|
||||||
/* Set the profile as imported. */
|
/* Set the profile as not importable (as it's imported). */
|
||||||
for (auto i = 0; i < m_importing_count; ++i) {
|
for (auto i = 0; i < m_importing_count; ++i) {
|
||||||
if (m_importing_profiles[i] == profile) {
|
if (m_importing_profiles[i].identifier_0 == profile) {
|
||||||
m_imported_profiles[i] = true;
|
m_is_profile_importable[i] = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,13 +126,39 @@ namespace ams::sprofile::srv {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to have imported everything we intended to import. */
|
/* We need to have imported everything we intended to import. */
|
||||||
return m_imported_profiles.PopCount() == m_importing_count;
|
return m_is_profile_importable.IsAllOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetImportingCount() const { return m_importing_count; }
|
int GetImportingCount() const { return m_importing_count; }
|
||||||
Identifier GetImportingProfile(int i) const { return m_importing_profiles[i]; }
|
const ImportingProfile &GetImportingProfile(int i) const { return m_importing_profiles[i]; }
|
||||||
|
|
||||||
Identifier GetRevisionKey() const { return m_revision_key; }
|
Identifier GetRevisionKey() const { return m_revision_key; }
|
||||||
|
|
||||||
|
Result CleanupOrphanedProfiles(auto cleanup_impl) const {
|
||||||
|
/* Cleanup any orphaned profiles in our metadata. */
|
||||||
|
if (m_metadata.has_value()) {
|
||||||
|
for (auto i = 0u; i < std::min<size_t>(m_metadata->num_entries, util::size(m_metadata->entries)); ++i) {
|
||||||
|
const auto &entry = m_metadata->entries[i];
|
||||||
|
if (!this->IsImportingProfile(entry.identifier_0)) {
|
||||||
|
R_TRY(cleanup_impl(entry.identifier_0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool IsImportingProfile(Identifier profile) const {
|
||||||
|
/* Check if we're importing the desired profile. */
|
||||||
|
for (auto i = 0; i < m_importing_count; ++i) {
|
||||||
|
if (m_importing_profiles[i].identifier_0 == profile) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're not importing the desired profile. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace ams::sprofile::srv {
|
||||||
R_TRY_CATCH(fs::CreateSystemSaveData(save_data_info.id, save_data_info.size, save_data_info.journal_size, save_data_info.flags)) {
|
R_TRY_CATCH(fs::CreateSystemSaveData(save_data_info.id, save_data_info.size, save_data_info.journal_size, save_data_info.flags)) {
|
||||||
R_CATCH(fs::ResultPathAlreadyExists) { /* Nintendo accepts already-existing savedata here. */ }
|
R_CATCH(fs::ResultPathAlreadyExists) { /* Nintendo accepts already-existing savedata here. */ }
|
||||||
} R_END_TRY_CATCH;
|
} R_END_TRY_CATCH;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SafePrint(char *dst, size_t dst_size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
|
void SafePrint(char *dst, size_t dst_size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
|
||||||
|
@ -135,20 +135,44 @@ namespace ams::sprofile::srv {
|
||||||
const auto result = fs::MountSystemSaveData(m_save_data_info.mount_name, m_save_data_info.id);
|
const auto result = fs::MountSystemSaveData(m_save_data_info.mount_name, m_save_data_info.id);
|
||||||
m_save_file_mounted = R_SUCCEEDED(result);
|
m_save_file_mounted = R_SUCCEEDED(result);
|
||||||
|
|
||||||
return result;
|
R_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::OpenProfileImporter() {
|
Result ProfileManager::OpenProfileImporter() {
|
||||||
/* Acquire locks. */
|
/* Acquire locks. */
|
||||||
std::scoped_lock lk1(m_profile_metadata_mutex);
|
std::scoped_lock lk1(m_profile_metadata_mutex);
|
||||||
std::scoped_lock lk2(m_profile_importer_mutex);
|
std::scoped_lock lk2(m_profile_importer_mutex);
|
||||||
|
std::scoped_lock lk3(m_general_mutex);
|
||||||
|
|
||||||
/* Check that we don't already have an importer. */
|
/* Check that we don't already have an importer. */
|
||||||
R_UNLESS(!m_profile_importer.has_value(), sprofile::ResultInvalidState());
|
R_UNLESS(!m_profile_importer.has_value(), sprofile::ResultInvalidState());
|
||||||
|
|
||||||
|
/* Try to load profile metadata. NOTE: result is not checked, it is okay if this fails. */
|
||||||
|
this->LoadPrimaryMetadataImpl();
|
||||||
|
|
||||||
/* Create importer. */
|
/* Create importer. */
|
||||||
m_profile_importer.emplace(m_profile_metadata);
|
m_profile_importer.emplace(m_profile_metadata);
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileManager::CloseProfileImporterImpl() {
|
||||||
|
/* Check pre-conditions. */
|
||||||
|
AMS_ASSERT(m_profile_importer_mutex.IsLockedByCurrentThread());
|
||||||
|
AMS_ASSERT(m_general_mutex.IsLockedByCurrentThread());
|
||||||
|
AMS_ASSERT(m_fs_mutex.IsLockedByCurrentThread());
|
||||||
|
|
||||||
|
if (m_profile_importer.has_value()) {
|
||||||
|
/* Unmount save file. */
|
||||||
|
fs::Unmount(m_save_data_info.mount_name);
|
||||||
|
m_save_file_mounted = false;
|
||||||
|
|
||||||
|
/* Re-mount save file. */
|
||||||
|
R_ABORT_UNLESS(fs::MountSystemSaveData(m_save_data_info.mount_name, m_save_data_info.id));
|
||||||
|
m_save_file_mounted = true;
|
||||||
|
|
||||||
|
/* Reset our importer. */
|
||||||
|
m_profile_importer = util::nullopt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileManager::CloseProfileImporter() {
|
void ProfileManager::CloseProfileImporter() {
|
||||||
|
@ -158,7 +182,7 @@ namespace ams::sprofile::srv {
|
||||||
std::scoped_lock lk3(m_fs_mutex);
|
std::scoped_lock lk3(m_fs_mutex);
|
||||||
|
|
||||||
/* Close our importer. */
|
/* Close our importer. */
|
||||||
m_profile_importer = util::nullopt;
|
this->CloseProfileImporterImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::ImportProfile(const sprofile::srv::ProfileDataForImportData &import) {
|
Result ProfileManager::ImportProfile(const sprofile::srv::ProfileDataForImportData &import) {
|
||||||
|
@ -202,7 +226,7 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Set profile imported. */
|
/* Set profile imported. */
|
||||||
m_profile_importer->OnImportProfile(import.header.identifier_0);
|
m_profile_importer->OnImportProfile(import.header.identifier_0);
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::Commit() {
|
Result ProfileManager::Commit() {
|
||||||
|
@ -218,33 +242,20 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Commit, and if we fail remount our save. */
|
/* Commit, and if we fail remount our save. */
|
||||||
{
|
{
|
||||||
/* Setup guard in case we fail. */
|
/* If we fail, close our importer. */
|
||||||
auto remount_guard = SCOPE_GUARD {
|
ON_RESULT_FAILURE { this->CloseProfileImporterImpl(); };
|
||||||
if (m_profile_importer.has_value()) {
|
|
||||||
/* Unmount save file. */
|
|
||||||
fs::Unmount(m_save_data_info.mount_name);
|
|
||||||
m_save_file_mounted = false;
|
|
||||||
|
|
||||||
/* Re-mount save file. */
|
|
||||||
R_ABORT_UNLESS(fs::MountSystemSaveData(m_save_data_info.mount_name, m_save_data_info.id));
|
|
||||||
m_save_file_mounted = true;
|
|
||||||
|
|
||||||
/* Reset our importer. */
|
|
||||||
m_profile_importer = util::nullopt;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Check that we can commit the importer. */
|
/* Check that we can commit the importer. */
|
||||||
R_UNLESS(m_profile_importer->CanCommit(), sprofile::ResultInvalidState());
|
R_UNLESS(m_profile_importer->CanCommit(), sprofile::ResultInvalidState());
|
||||||
|
|
||||||
/* Commit. */
|
/* Commit newly imported profiles. */
|
||||||
R_TRY(this->CommitImpl());
|
R_TRY(this->CommitImportedProfiles());
|
||||||
|
|
||||||
|
/* Cleanup orphaned profiles. */
|
||||||
|
R_TRY(this->CleanupOrphanedProfiles());
|
||||||
|
|
||||||
/* Commit the save file. */
|
/* Commit the save file. */
|
||||||
R_TRY(fs::CommitSaveData(m_save_data_info.mount_name));
|
R_TRY(fs::CommitSaveData(m_save_data_info.mount_name));
|
||||||
|
|
||||||
/* We successfully committed. */
|
|
||||||
remount_guard.Cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: Here nintendo generates an "sprofile_update_profile" sreport with the new and old revision keys. */
|
/* NOTE: Here nintendo generates an "sprofile_update_profile" sreport with the new and old revision keys. */
|
||||||
|
@ -252,7 +263,7 @@ namespace ams::sprofile::srv {
|
||||||
/* Handle tasks for when we've committed (including notifying update observers). */
|
/* Handle tasks for when we've committed (including notifying update observers). */
|
||||||
this->OnCommitted();
|
this->OnCommitted();
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import) {
|
Result ProfileManager::ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import) {
|
||||||
|
@ -292,7 +303,28 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Import the metadata. */
|
/* Import the metadata. */
|
||||||
m_profile_importer->ImportMetadata(import.metadata);
|
m_profile_importer->ImportMetadata(import.metadata);
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ProfileManager::LoadPrimaryMetadataImpl() {
|
||||||
|
/* Check pre-conditions. */
|
||||||
|
AMS_ASSERT(m_profile_metadata_mutex.IsLockedByCurrentThread());
|
||||||
|
AMS_ASSERT(m_general_mutex.IsLockedByCurrentThread());
|
||||||
|
|
||||||
|
/* If we don't have metadata, load it. */
|
||||||
|
if (!m_profile_metadata.has_value()) {
|
||||||
|
/* Emplace our metadata. */
|
||||||
|
m_profile_metadata.emplace();
|
||||||
|
ON_RESULT_FAILURE { m_profile_metadata = util::nullopt; };
|
||||||
|
|
||||||
|
/* Read profile metadata. */
|
||||||
|
char path[0x30];
|
||||||
|
CreatePrimaryMetadataPath(path, sizeof(path), m_save_data_info.mount_name);
|
||||||
|
R_TRY(ReadFile(path, std::addressof(*m_profile_metadata), sizeof(*m_profile_metadata), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We now have loaded metadata. */
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::LoadPrimaryMetadata(ProfileMetadata *out) {
|
Result ProfileManager::LoadPrimaryMetadata(ProfileMetadata *out) {
|
||||||
|
@ -300,24 +332,12 @@ namespace ams::sprofile::srv {
|
||||||
std::scoped_lock lk1(m_profile_metadata_mutex);
|
std::scoped_lock lk1(m_profile_metadata_mutex);
|
||||||
std::scoped_lock lk2(m_general_mutex);
|
std::scoped_lock lk2(m_general_mutex);
|
||||||
|
|
||||||
/* If we don't have metadata, load it. */
|
/* Load our metadata. */
|
||||||
if (!m_profile_metadata.has_value()) {
|
R_TRY(this->LoadPrimaryMetadataImpl());
|
||||||
/* Emplace our metadata. */
|
|
||||||
m_profile_metadata.emplace();
|
|
||||||
auto meta_guard = SCOPE_GUARD { m_profile_metadata = util::nullopt; };
|
|
||||||
|
|
||||||
/* Read profile metadata. */
|
|
||||||
char path[0x30];
|
|
||||||
CreatePrimaryMetadataPath(path, sizeof(path), m_save_data_info.mount_name);
|
|
||||||
R_TRY(ReadFile(path, std::addressof(*m_profile_metadata), sizeof(*m_profile_metadata), 0));
|
|
||||||
|
|
||||||
/* We read the metadata successfully. */
|
|
||||||
meta_guard.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the output. */
|
/* Set the output. */
|
||||||
*out = *m_profile_metadata;
|
*out = *m_profile_metadata;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::LoadProfile(Identifier profile) {
|
Result ProfileManager::LoadProfile(Identifier profile) {
|
||||||
|
@ -339,7 +359,7 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* We succeeded. */
|
/* We succeeded. */
|
||||||
prof_guard.Cancel();
|
prof_guard.Cancel();
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::GetDataEntry(ProfileDataEntry *out, Identifier profile, Identifier key) {
|
Result ProfileManager::GetDataEntry(ProfileDataEntry *out, Identifier profile, Identifier key) {
|
||||||
|
@ -353,12 +373,12 @@ namespace ams::sprofile::srv {
|
||||||
for (auto i = 0u; i < std::min<size_t>(m_service_profile->data.num_entries, util::size(m_service_profile->data.entries)); ++i) {
|
for (auto i = 0u; i < std::min<size_t>(m_service_profile->data.num_entries, util::size(m_service_profile->data.entries)); ++i) {
|
||||||
if (m_service_profile->data.entries[i].key == key) {
|
if (m_service_profile->data.entries[i].key == key) {
|
||||||
*out = m_service_profile->data.entries[i];
|
*out = m_service_profile->data.entries[i];
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprofile::ResultKeyNotFound();
|
R_THROW(sprofile::ResultKeyNotFound());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::GetSigned64(s64 *out, Identifier profile, Identifier key) {
|
Result ProfileManager::GetSigned64(s64 *out, Identifier profile, Identifier key) {
|
||||||
|
@ -371,7 +391,7 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Set the output value. */
|
/* Set the output value. */
|
||||||
*out = entry.value_s64;
|
*out = entry.value_s64;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::GetUnsigned64(u64 *out, Identifier profile, Identifier key) {
|
Result ProfileManager::GetUnsigned64(u64 *out, Identifier profile, Identifier key) {
|
||||||
|
@ -384,7 +404,7 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Set the output value. */
|
/* Set the output value. */
|
||||||
*out = entry.value_u64;
|
*out = entry.value_u64;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::GetSigned32(s32 *out, Identifier profile, Identifier key) {
|
Result ProfileManager::GetSigned32(s32 *out, Identifier profile, Identifier key) {
|
||||||
|
@ -397,7 +417,7 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Set the output value. */
|
/* Set the output value. */
|
||||||
*out = entry.value_s32;
|
*out = entry.value_s32;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::GetUnsigned32(u32 *out, Identifier profile, Identifier key) {
|
Result ProfileManager::GetUnsigned32(u32 *out, Identifier profile, Identifier key) {
|
||||||
|
@ -410,7 +430,7 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Set the output value. */
|
/* Set the output value. */
|
||||||
*out = entry.value_u32;
|
*out = entry.value_u32;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::GetByte(u8 *out, Identifier profile, Identifier key) {
|
Result ProfileManager::GetByte(u8 *out, Identifier profile, Identifier key) {
|
||||||
|
@ -423,7 +443,7 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Set the output value. */
|
/* Set the output value. */
|
||||||
*out = entry.value_u8;
|
*out = entry.value_u8;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::GetRaw(u8 *out_type, u64 *out_value, Identifier profile, Identifier key) {
|
Result ProfileManager::GetRaw(u8 *out_type, u64 *out_value, Identifier profile, Identifier key) {
|
||||||
|
@ -434,10 +454,10 @@ namespace ams::sprofile::srv {
|
||||||
/* Set the output type and value. */
|
/* Set the output type and value. */
|
||||||
*out_type = entry.type;
|
*out_type = entry.type;
|
||||||
*out_value = entry.value_u64;
|
*out_value = entry.value_u64;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::CommitImpl() {
|
Result ProfileManager::CommitImportedProfiles() {
|
||||||
/* Ensure primary directories. */
|
/* Ensure primary directories. */
|
||||||
R_TRY(this->EnsurePrimaryDirectories());
|
R_TRY(this->EnsurePrimaryDirectories());
|
||||||
|
|
||||||
|
@ -452,16 +472,32 @@ namespace ams::sprofile::srv {
|
||||||
R_TRY(MoveFile(tmp_path, pri_path));
|
R_TRY(MoveFile(tmp_path, pri_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move all profiles. */
|
/* Move all newly imported profiles. */
|
||||||
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
|
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
|
||||||
const auto id = m_profile_importer->GetImportingProfile(i);
|
const auto &profile = m_profile_importer->GetImportingProfile(i);
|
||||||
|
|
||||||
CreateTemporaryProfilePath(tmp_path, sizeof(tmp_path), m_save_data_info.mount_name, id);
|
if (profile.is_new_import) {
|
||||||
CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, id);
|
CreateTemporaryProfilePath(tmp_path, sizeof(tmp_path), m_save_data_info.mount_name, profile.identifier_0);
|
||||||
|
CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, profile.identifier_0);
|
||||||
R_TRY(MoveFile(tmp_path, pri_path));
|
R_TRY(MoveFile(tmp_path, pri_path));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ProfileManager::CleanupOrphanedProfiles() {
|
||||||
|
/* Check pre-conditions. */
|
||||||
|
AMS_ASSERT(m_profile_importer.has_value());
|
||||||
|
|
||||||
|
/* Declare re-usable path. */
|
||||||
|
char pri_path[0x30];
|
||||||
|
|
||||||
|
/* Cleanup the profiles. */
|
||||||
|
R_RETURN(m_profile_importer->CleanupOrphanedProfiles([&](Identifier profile) ALWAYS_INLINE_LAMBDA -> Result {
|
||||||
|
CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, profile);
|
||||||
|
R_RETURN(DeleteFile(pri_path));
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileManager::OnCommitted() {
|
void ProfileManager::OnCommitted() {
|
||||||
|
@ -470,7 +506,7 @@ namespace ams::sprofile::srv {
|
||||||
/* If we need to, invalidate the loaded service profile. */
|
/* If we need to, invalidate the loaded service profile. */
|
||||||
if (m_service_profile.has_value()) {
|
if (m_service_profile.has_value()) {
|
||||||
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
|
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
|
||||||
if (m_service_profile->name == m_profile_importer->GetImportingProfile(i)) {
|
if (m_service_profile->name == m_profile_importer->GetImportingProfile(i).identifier_0) {
|
||||||
m_service_profile = util::nullopt;
|
m_service_profile = util::nullopt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +518,11 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
/* Invoke any listeners. */
|
/* Invoke any listeners. */
|
||||||
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
|
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
|
||||||
m_update_observer_manager.OnUpdate(m_profile_importer->GetImportingProfile(i));
|
const auto &profile = m_profile_importer->GetImportingProfile(i);
|
||||||
|
|
||||||
|
if (profile.is_new_import) {
|
||||||
|
m_update_observer_manager.OnUpdate(profile.identifier_0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset profile importer. */
|
/* Reset profile importer. */
|
||||||
|
@ -499,7 +539,7 @@ namespace ams::sprofile::srv {
|
||||||
CreatePrimaryProfileDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
|
CreatePrimaryProfileDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
|
||||||
R_TRY(EnsureDirectory(path));
|
R_TRY(EnsureDirectory(path));
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileManager::EnsureTemporaryDirectories() {
|
Result ProfileManager::EnsureTemporaryDirectories() {
|
||||||
|
@ -512,7 +552,7 @@ namespace ams::sprofile::srv {
|
||||||
CreateTemporaryProfileDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
|
CreateTemporaryProfileDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
|
||||||
R_TRY(EnsureDirectory(path));
|
R_TRY(EnsureDirectory(path));
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,11 @@ namespace ams::sprofile::srv {
|
||||||
|
|
||||||
ProfileUpdateObserverManager &GetUpdateObserverManager() { return m_update_observer_manager; }
|
ProfileUpdateObserverManager &GetUpdateObserverManager() { return m_update_observer_manager; }
|
||||||
private:
|
private:
|
||||||
Result CommitImpl();
|
Result CommitImportedProfiles();
|
||||||
|
Result CleanupOrphanedProfiles();
|
||||||
|
|
||||||
|
Result LoadPrimaryMetadataImpl();
|
||||||
|
void CloseProfileImporterImpl();
|
||||||
|
|
||||||
void OnCommitted();
|
void OnCommitted();
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,11 @@ namespace ams::sprofile::srv {
|
||||||
AutoUnregisterObserver(ProfileUpdateObserverManager *manager) : m_manager(manager) { /* ... */ }
|
AutoUnregisterObserver(ProfileUpdateObserverManager *manager) : m_manager(manager) { /* ... */ }
|
||||||
virtual ~AutoUnregisterObserver() { m_manager->CloseObserver(this); }
|
virtual ~AutoUnregisterObserver() { m_manager->CloseObserver(this); }
|
||||||
};
|
};
|
||||||
static_assert(sprofile::IsIProfileUpdateObserver<AutoUnregisterObserver>);
|
static_assert(sprofile::srv::IsIProfileUpdateObserver<AutoUnregisterObserver>);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileUpdateObserverManager::OpenObserver(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileUpdateObserver>> &out, MemoryResource *memory_resource) {
|
Result ProfileUpdateObserverManager::OpenObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> &out, MemoryResource *memory_resource) {
|
||||||
/* Lock ourselves. */
|
/* Lock ourselves. */
|
||||||
std::scoped_lock lk(m_mutex);
|
std::scoped_lock lk(m_mutex);
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace ams::sprofile::srv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert(sprofile::IsIProfileUpdateObserver<ProfileUpdateObserverImpl>);
|
static_assert(sprofile::srv::IsIProfileUpdateObserver<ProfileUpdateObserverImpl>);
|
||||||
|
|
||||||
class ProfileUpdateObserverManager {
|
class ProfileUpdateObserverManager {
|
||||||
public:
|
public:
|
||||||
|
@ -90,7 +90,7 @@ namespace ams::sprofile::srv {
|
||||||
public:
|
public:
|
||||||
ProfileUpdateObserverManager() : m_observer_count(0), m_mutex() { /* ... */ }
|
ProfileUpdateObserverManager() : m_observer_count(0), m_mutex() { /* ... */ }
|
||||||
public:
|
public:
|
||||||
Result OpenObserver(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileUpdateObserver>> &out, MemoryResource *memory_resource);
|
Result OpenObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> &out, MemoryResource *memory_resource);
|
||||||
void CloseObserver(ProfileUpdateObserverImpl *observer);
|
void CloseObserver(ProfileUpdateObserverImpl *observer);
|
||||||
|
|
||||||
void OnUpdate(Identifier profile) {
|
void OnUpdate(Identifier profile) {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
namespace ams::sprofile::srv {
|
namespace ams::sprofile::srv {
|
||||||
|
|
||||||
Result ServiceForBgAgent::OpenProfileImporter(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileImporter>> out) {
|
Result ServiceForBgAgent::OpenProfileImporter(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileImporter>> out) {
|
||||||
/* Allocate an object. */
|
/* Allocate an object. */
|
||||||
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileImporter, ProfileImporterImpl>(m_memory_resource, m_profile_manager);
|
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileImporter, ProfileImporterImpl>(m_memory_resource, m_profile_manager);
|
||||||
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
|
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
|
||||||
|
|
|
@ -28,11 +28,11 @@ namespace ams::sprofile::srv {
|
||||||
public:
|
public:
|
||||||
constexpr ServiceForBgAgent(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ }
|
constexpr ServiceForBgAgent(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ }
|
||||||
public:
|
public:
|
||||||
Result OpenProfileImporter(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileImporter>> out);
|
Result OpenProfileImporter(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileImporter>> out);
|
||||||
Result GetImportableProfileUrls(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg);
|
Result GetImportableProfileUrls(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg);
|
||||||
Result IsUpdateNeeded(sf::Out<bool> out, Identifier revision_key);
|
Result IsUpdateNeeded(sf::Out<bool> out, Identifier revision_key);
|
||||||
Result Reset();
|
Result Reset();
|
||||||
};
|
};
|
||||||
static_assert(sprofile::IsISprofileServiceForBgAgent<ServiceForBgAgent>);
|
static_assert(sprofile::srv::IsISprofileServiceForBgAgent<ServiceForBgAgent>);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
namespace ams::sprofile::srv {
|
namespace ams::sprofile::srv {
|
||||||
|
|
||||||
Result ServiceForSystemProcess::OpenProfileReader(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileReader>> out) {
|
Result ServiceForSystemProcess::OpenProfileReader(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileReader>> out) {
|
||||||
/* Allocate an object. */
|
/* Allocate an object. */
|
||||||
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileReader, ProfileReaderImpl>(m_memory_resource, m_profile_manager);
|
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileReader, ProfileReaderImpl>(m_memory_resource, m_profile_manager);
|
||||||
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
|
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
|
||||||
|
@ -31,11 +31,11 @@ namespace ams::sprofile::srv {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServiceForSystemProcess::OpenProfileUpdateObserver(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileUpdateObserver>> out) {
|
Result ServiceForSystemProcess::OpenProfileUpdateObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> out) {
|
||||||
return m_profile_manager->GetUpdateObserverManager().OpenObserver(out, m_memory_resource);
|
return m_profile_manager->GetUpdateObserverManager().OpenObserver(out, m_memory_resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServiceForSystemProcess::OpenProfileControllerForDebug(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileControllerForDebug>> out) {
|
Result ServiceForSystemProcess::OpenProfileControllerForDebug(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileControllerForDebug>> out) {
|
||||||
/* Require debug mode in order to open a debug controller. */
|
/* Require debug mode in order to open a debug controller. */
|
||||||
R_UNLESS(settings::fwdbg::IsDebugModeEnabled(), sprofile::ResultNotPermitted());
|
R_UNLESS(settings::fwdbg::IsDebugModeEnabled(), sprofile::ResultNotPermitted());
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,10 @@ namespace ams::sprofile::srv {
|
||||||
public:
|
public:
|
||||||
constexpr ServiceForSystemProcess(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ }
|
constexpr ServiceForSystemProcess(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ }
|
||||||
public:
|
public:
|
||||||
Result OpenProfileReader(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileReader>> out);
|
Result OpenProfileReader(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileReader>> out);
|
||||||
Result OpenProfileUpdateObserver(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileUpdateObserver>> out);
|
Result OpenProfileUpdateObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> out);
|
||||||
Result OpenProfileControllerForDebug(sf::Out<sf::SharedPointer<::ams::sprofile::IProfileControllerForDebug>> out);
|
Result OpenProfileControllerForDebug(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileControllerForDebug>> out);
|
||||||
};
|
};
|
||||||
static_assert(sprofile::IsISprofileServiceForSystemProcess<ServiceForSystemProcess>);
|
static_assert(sprofile::srv::IsISprofileServiceForSystemProcess<ServiceForSystemProcess>);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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 "sprofile_srv_service_getter.hpp"
|
||||||
|
|
||||||
|
namespace ams::sprofile::srv {
|
||||||
|
|
||||||
|
Result ServiceGetter::GetServiceForSystemProcess(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForSystemProcess>> out) {
|
||||||
|
/* Check that we have a service-for-system-process. */
|
||||||
|
R_UNLESS(m_service_for_system_process != nullptr, sprofile::ResultNotPermitted());
|
||||||
|
|
||||||
|
/* Set the output. */
|
||||||
|
*out = m_service_for_system_process;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ServiceGetter::GetServiceForBgAgent(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForBgAgent>> out) {
|
||||||
|
/* Check that we have a service-for-bg-agent. */
|
||||||
|
R_UNLESS(m_service_for_bg_agent != nullptr, sprofile::ResultNotPermitted());
|
||||||
|
|
||||||
|
/* Set the output. */
|
||||||
|
*out = m_service_for_bg_agent;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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 "sprofile_srv_i_service_getter.hpp"
|
||||||
|
|
||||||
|
namespace ams::sprofile::srv {
|
||||||
|
|
||||||
|
class ServiceGetter {
|
||||||
|
private:
|
||||||
|
sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForBgAgent> m_service_for_bg_agent;
|
||||||
|
sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForSystemProcess> m_service_for_system_process;
|
||||||
|
public:
|
||||||
|
constexpr ServiceGetter(sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForBgAgent> &&bg, sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForSystemProcess> &&sp) : m_service_for_bg_agent(bg), m_service_for_system_process(sp) { /* ... */ }
|
||||||
|
public:
|
||||||
|
Result GetServiceForSystemProcess(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForSystemProcess>> out);
|
||||||
|
Result GetServiceForBgAgent(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForBgAgent>> out);
|
||||||
|
};
|
||||||
|
static_assert(sprofile::srv::IsIServiceGetter<ServiceGetter>);
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue