ams: support building unit test programs on windows/linux/macos
This commit is contained in:
@@ -14,28 +14,37 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "ncm_content_manager_factory.hpp"
|
||||
#include "ncm_remote_content_manager_impl.hpp"
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
namespace {
|
||||
|
||||
sf::SharedPointer<IContentManager> g_content_manager;
|
||||
constinit sf::SharedPointer<IContentManager> g_content_manager;
|
||||
|
||||
sf::UnmanagedServiceObject<IContentManager, RemoteContentManagerImpl> g_remote_manager_impl;
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
constinit util::TypedStorage<sf::UnmanagedServiceObject<IContentManager, RemoteContentManagerImpl>> g_remote_manager_storage = {};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
AMS_ASSERT(g_content_manager == nullptr);
|
||||
R_ABORT_UNLESS(ncmInitialize());
|
||||
g_content_manager = g_remote_manager_impl.GetShared();
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
util::ConstructAt(g_remote_manager_storage);
|
||||
g_content_manager = util::GetReference(g_remote_manager_storage).GetShared();
|
||||
#else
|
||||
g_content_manager = CreateDefaultContentManager(ContentManagerConfig{});
|
||||
#endif
|
||||
}
|
||||
|
||||
void Finalize() {
|
||||
AMS_ASSERT(g_content_manager != nullptr);
|
||||
g_content_manager.Reset();
|
||||
ncmExit();
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
util::DestroyAt(g_remote_manager_storage);
|
||||
#endif
|
||||
}
|
||||
|
||||
void InitializeWithObject(sf::SharedPointer<IContentManager> manager_object) {
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace ams::ncm {
|
||||
/* Convert each character pair to a byte until we reach the end. */
|
||||
for (size_t i = 0; i < src_size; i += 2) {
|
||||
char tmp[3];
|
||||
strlcpy(tmp, src + i, sizeof(tmp));
|
||||
util::Strlcpy(tmp, src + i, sizeof(tmp));
|
||||
|
||||
char *err = nullptr;
|
||||
reinterpret_cast<u8 *>(dst)[i / 2] = static_cast<u8>(std::strtoul(tmp, std::addressof(err), 16));
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 "ncm_content_manager_factory.hpp"
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
sf::SharedPointer<IContentManager> CreateDefaultContentManager(const ContentManagerConfig &config) {
|
||||
auto ref = sf::CreateSharedObjectEmplaced<IContentManager, ContentManagerImpl>();
|
||||
R_ABORT_UNLESS(ref.GetImpl().Initialize(config));
|
||||
return ref;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
sf::SharedPointer<IContentManager> CreateDefaultContentManager(const ContentManagerConfig &config);
|
||||
|
||||
}
|
||||
@@ -266,7 +266,7 @@ namespace ams::ncm {
|
||||
ON_SCOPE_EXIT { fs::Unmount(root->mount_name); };
|
||||
|
||||
/* Ensure the path exists for us to import to. */
|
||||
R_TRY(fs::EnsureDirectoryRecursively(root->path));
|
||||
R_TRY(fs::EnsureDirectory(root->path));
|
||||
|
||||
/* Copy the file from bis to our save. */
|
||||
R_TRY(impl::CopyFile(savedata_db_path, bis_db_path));
|
||||
@@ -395,7 +395,7 @@ namespace ams::ncm {
|
||||
ON_SCOPE_EXIT { fs::Unmount(root->mount_name); };
|
||||
|
||||
/* Ensure the content storage root's path exists. */
|
||||
R_TRY(fs::EnsureDirectoryRecursively(root->path));
|
||||
R_TRY(fs::EnsureDirectory(root->path));
|
||||
|
||||
/* Initialize content and placeholder directories for the root. */
|
||||
return ContentStorageImpl::InitializeBase(root->path);
|
||||
@@ -415,7 +415,7 @@ namespace ams::ncm {
|
||||
ON_SCOPE_EXIT { fs::Unmount(root->mount_name); };
|
||||
|
||||
/* Ensure the content meta database root's path exists. */
|
||||
R_TRY(fs::EnsureDirectoryRecursively(root->path));
|
||||
R_TRY(fs::EnsureDirectory(root->path));
|
||||
|
||||
/* Commit our changes. */
|
||||
return fs::CommitSaveData(root->mount_name);
|
||||
@@ -542,7 +542,7 @@ namespace ams::ncm {
|
||||
|
||||
/* Mount based on the storage type. */
|
||||
if (storage_id == StorageId::GameCard) {
|
||||
fs::GameCardHandle handle;
|
||||
fs::GameCardHandle handle{};
|
||||
R_TRY(fs::GetGameCardHandle(std::addressof(handle)));
|
||||
R_TRY(fs::MountGameCardPartition(root->mount_name, handle, fs::GameCardPartition::Secure));
|
||||
} else {
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace ams::ncm {
|
||||
PackagedContentMetaReader reader(meta.Get(), meta.GetSize());
|
||||
|
||||
/* Define a helper to output the base meta infos. */
|
||||
const auto ReadMetaInfoListFromBase = [&] ALWAYS_INLINE_LAMBDA () -> Result {
|
||||
const auto ReadMetaInfoListFromBase = [&] () ALWAYS_INLINE_LAMBDA -> Result {
|
||||
/* Output the base content meta info count. */
|
||||
*out_count = reader.GetContentMetaCount();
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace ams::ncm {
|
||||
Result EnsureContentDirectory(ContentId id, MakeContentPathFunction func, const char *root_path) {
|
||||
PathString path;
|
||||
MakeContentPath(std::addressof(path), id, func, root_path);
|
||||
return fs::EnsureParentDirectoryRecursively(path);
|
||||
return fs::EnsureParentDirectory(path);
|
||||
}
|
||||
|
||||
Result DeleteContentFile(ContentId id, MakeContentPathFunction func, const char *root_path) {
|
||||
@@ -303,11 +303,11 @@ namespace ams::ncm {
|
||||
|
||||
/* Create the content directory. */
|
||||
MakeBaseContentDirectoryPath(std::addressof(path), root_path);
|
||||
R_TRY(fs::EnsureDirectoryRecursively(path));
|
||||
R_TRY(fs::EnsureDirectory(path));
|
||||
|
||||
/* Create the placeholder directory. */
|
||||
PlaceHolderAccessor::MakeBaseDirectoryPath(std::addressof(path), root_path);
|
||||
return fs::EnsureDirectoryRecursively(path);
|
||||
return fs::EnsureDirectory(path);
|
||||
}
|
||||
|
||||
Result ContentStorageImpl::CleanupBase(const char *root_path) {
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace ams::ncm {
|
||||
fs::DirectoryEntry m_entries[MaxDirectoryEntries]{};
|
||||
s64 m_entry_count{};
|
||||
public:
|
||||
constexpr ContentIterator() = default;
|
||||
constexpr ContentIterator() { /* ... */ }
|
||||
~ContentIterator();
|
||||
|
||||
Result Initialize(const char *root_path, size_t max_depth);
|
||||
@@ -48,6 +48,7 @@ namespace ams::ncm {
|
||||
Result OpenDirectory(const char *dir);
|
||||
Result LoadEntries();
|
||||
};
|
||||
static_assert(std::is_constructible<ContentIterator>::value);
|
||||
protected:
|
||||
PlaceHolderAccessor m_placeholder_accessor;
|
||||
ContentId m_cached_content_id;
|
||||
|
||||
@@ -39,19 +39,19 @@ namespace ams::ncm {
|
||||
|
||||
u16 Get16BitSha256HashPrefix(ContentId id) {
|
||||
u8 hash[crypto::Sha256Generator::HashSize];
|
||||
crypto::GenerateSha256Hash(hash, sizeof(hash), std::addressof(id), sizeof(id));
|
||||
crypto::GenerateSha256(hash, sizeof(hash), std::addressof(id), sizeof(id));
|
||||
return static_cast<u16>(hash[0]) | (static_cast<u16>(hash[1]) << 8);
|
||||
}
|
||||
|
||||
u8 Get8BitSha256HashPrefix(ContentId id) {
|
||||
u8 hash[crypto::Sha256Generator::HashSize];
|
||||
crypto::GenerateSha256Hash(hash, sizeof(hash), std::addressof(id), sizeof(id));
|
||||
crypto::GenerateSha256(hash, sizeof(hash), std::addressof(id), sizeof(id));
|
||||
return hash[0];
|
||||
}
|
||||
|
||||
u8 Get8BitSha256HashPrefix(PlaceHolderId id) {
|
||||
u8 hash[crypto::Sha256Generator::HashSize];
|
||||
crypto::GenerateSha256Hash(hash, sizeof(hash), std::addressof(id), sizeof(id));
|
||||
crypto::GenerateSha256(hash, sizeof(hash), std::addressof(id), sizeof(id));
|
||||
return hash[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,6 @@ namespace ams::ncm {
|
||||
func(out, id, path);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result ConvertNotFoundResult(Result r) {
|
||||
R_TRY_CATCH(r) {
|
||||
R_CONVERT(ams::fs::ResultPathNotFound, ncm::ResultPlaceHolderNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PlaceHolderAccessor::MakePath(PathString *out_placeholder_path, PlaceHolderId placeholder_id) const {
|
||||
@@ -59,7 +52,7 @@ namespace ams::ncm {
|
||||
Result PlaceHolderAccessor::EnsurePlaceHolderDirectory(PlaceHolderId placeholder_id) {
|
||||
PathString path;
|
||||
this->MakePath(std::addressof(path), placeholder_id);
|
||||
return fs::EnsureParentDirectoryRecursively(path);
|
||||
return fs::EnsureParentDirectory(path);
|
||||
}
|
||||
|
||||
Result PlaceHolderAccessor::GetPlaceHolderIdFromFileName(PlaceHolderId *out, const char *name) {
|
||||
@@ -71,7 +64,7 @@ namespace ams::ncm {
|
||||
PlaceHolderId placeholder_id = {};
|
||||
for (size_t i = 0; i < sizeof(placeholder_id); i++) {
|
||||
char tmp[3];
|
||||
strlcpy(tmp, name + i * 2, sizeof(tmp));
|
||||
util::Strlcpy(tmp, name + i * 2, sizeof(tmp));
|
||||
|
||||
char *err = nullptr;
|
||||
reinterpret_cast<u8 *>(std::addressof(placeholder_id))[i] = static_cast<u8>(std::strtoul(tmp, std::addressof(err), 16));
|
||||
|
||||
@@ -20,14 +20,15 @@
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
class RemoteContentManagerImpl {
|
||||
private:
|
||||
/* TODO: sf::ProxyObjectAllocator */
|
||||
using ObjectFactory = sf::ObjectFactory<sf::StdAllocationPolicy<std::allocator>>;
|
||||
public:
|
||||
RemoteContentManagerImpl() { /* ... */ }
|
||||
RemoteContentManagerImpl() { R_ABORT_UNLESS(::ncmInitialize()); }
|
||||
|
||||
~RemoteContentManagerImpl() { /* ... */ }
|
||||
~RemoteContentManagerImpl() { ::ncmExit(); }
|
||||
public:
|
||||
Result CreateContentStorage(StorageId storage_id) {
|
||||
return ::ncmCreateContentStorage(static_cast<NcmStorageId>(storage_id));
|
||||
@@ -100,5 +101,6 @@ namespace ams::ncm {
|
||||
}
|
||||
};
|
||||
static_assert(ncm::IsIContentManager<RemoteContentManagerImpl>);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
class RemoteContentMetaDatabaseImpl {
|
||||
private:
|
||||
::NcmContentMetaDatabase m_srv;
|
||||
@@ -169,5 +170,6 @@ namespace ams::ncm {
|
||||
}
|
||||
};
|
||||
static_assert(ncm::IsIContentMetaDatabase<RemoteContentMetaDatabaseImpl>);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
class RemoteContentStorageImpl {
|
||||
private:
|
||||
::NcmContentStorage m_srv;
|
||||
@@ -209,5 +210,6 @@ namespace ams::ncm {
|
||||
}
|
||||
};
|
||||
static_assert(ncm::IsIContentStorage<RemoteContentStorageImpl>);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -80,28 +80,6 @@ namespace ams::ncm {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char * const StorageIdStrings[] = {
|
||||
"None",
|
||||
"Host",
|
||||
"GameCard",
|
||||
"BuiltInSystem",
|
||||
"BuiltInUser",
|
||||
"SdCard"
|
||||
};
|
||||
|
||||
constexpr const char * const StorageIdStringsForPlayReport[] = {
|
||||
"None",
|
||||
"Host",
|
||||
"Card",
|
||||
"BuildInSystem",
|
||||
"BuildInUser",
|
||||
"SdCard"
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const char *GetStorageIdString(StorageId storage_id) {
|
||||
switch (storage_id) {
|
||||
case StorageId::None: return "None";
|
||||
|
||||
Reference in New Issue
Block a user