summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys/registered_cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/file_sys/registered_cache.cpp')
-rw-r--r--src/core/file_sys/registered_cache.cpp151
1 files changed, 137 insertions, 14 deletions
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index dacf8568b..dad7ae10b 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -5,13 +5,17 @@
#include <regex>
#include <mbedtls/sha256.h>
#include "common/assert.h"
+#include "common/file_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
-#include "core/crypto/encryption_layer.h"
+#include "core/crypto/key_manager.h"
#include "core/file_sys/card_image.h"
+#include "core/file_sys/content_archive.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/registered_cache.h"
+#include "core/file_sys/submission_package.h"
#include "core/file_sys/vfs_concat.h"
+#include "core/loader/loader.h"
namespace FileSys {
std::string RegisteredCacheEntry::DebugInfo() const {
@@ -58,11 +62,11 @@ static std::string GetCNMTName(TitleType type, u64 title_id) {
"" ///< Currently unknown 'DeltaTitle'
};
- auto index = static_cast<size_t>(type);
+ auto index = static_cast<std::size_t>(type);
// If the index is after the jump in TitleType, subtract it out.
- if (index >= static_cast<size_t>(TitleType::Application)) {
- index -= static_cast<size_t>(TitleType::Application) -
- static_cast<size_t>(TitleType::FirmwarePackageB);
+ if (index >= static_cast<std::size_t>(TitleType::Application)) {
+ index -= static_cast<std::size_t>(TitleType::Application) -
+ static_cast<std::size_t>(TitleType::FirmwarePackageB);
}
return fmt::format("{}_{:016x}.cnmt", TITLE_TYPE_NAMES[index], title_id);
}
@@ -101,7 +105,7 @@ VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
} else {
std::vector<VirtualFile> concat;
// Since the files are a two-digit hex number, max is FF.
- for (size_t i = 0; i < 0x100; ++i) {
+ for (std::size_t i = 0; i < 0x100; ++i) {
auto next = nca_dir->GetFile(fmt::format("{:02X}", i));
if (next != nullptr) {
concat.push_back(std::move(next));
@@ -276,6 +280,18 @@ VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const
return GetEntryUnparsed(entry.title_id, entry.type);
}
+boost::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
+ const auto meta_iter = meta.find(title_id);
+ if (meta_iter != meta.end())
+ return meta_iter->second.GetTitleVersion();
+
+ const auto yuzu_meta_iter = yuzu_meta.find(title_id);
+ if (yuzu_meta_iter != yuzu_meta.end())
+ return yuzu_meta_iter->second.GetTitleVersion();
+
+ return boost::none;
+}
+
VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const {
const auto id = GetNcaIDFromMetadata(title_id, type);
if (id == boost::none)
@@ -355,17 +371,21 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
return out;
}
-static std::shared_ptr<NCA> GetNCAFromXCIForID(std::shared_ptr<XCI> xci, const NcaID& id) {
- const auto filename = fmt::format("{}.nca", Common::HexArrayToString(id, false));
- const auto iter =
- std::find_if(xci->GetNCAs().begin(), xci->GetNCAs().end(),
- [&filename](std::shared_ptr<NCA> nca) { return nca->GetName() == filename; });
- return iter == xci->GetNCAs().end() ? nullptr : *iter;
+static std::shared_ptr<NCA> GetNCAFromNSPForID(std::shared_ptr<NSP> nsp, const NcaID& id) {
+ const auto file = nsp->GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
+ if (file == nullptr)
+ return nullptr;
+ return std::make_shared<NCA>(file);
}
InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists,
const VfsCopyFunction& copy) {
- const auto& ncas = xci->GetNCAs();
+ return InstallEntry(xci->GetSecurePartitionNSP(), overwrite_if_exists, copy);
+}
+
+InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists,
+ const VfsCopyFunction& copy) {
+ const auto& ncas = nsp->GetNCAsCollapsed();
const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr<NCA> nca) {
return nca->GetType() == NCAContentType::Meta;
});
@@ -389,7 +409,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overw
const auto cnmt_file = section0->GetFiles()[0];
const CNMT cnmt(cnmt_file);
for (const auto& record : cnmt.GetContentRecords()) {
- const auto nca = GetNCAFromXCIForID(xci, record.nca_id);
+ const auto nca = GetNCAFromNSPForID(nsp, record.nca_id);
if (nca == nullptr)
return InstallResult::ErrorCopyFailed;
const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id);
@@ -490,4 +510,107 @@ bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) {
kv.second.GetTitleID() == cnmt.GetTitleID();
}) != yuzu_meta.end();
}
+
+RegisteredCacheUnion::RegisteredCacheUnion(std::vector<std::shared_ptr<RegisteredCache>> caches)
+ : caches(std::move(caches)) {}
+
+void RegisteredCacheUnion::Refresh() {
+ for (const auto& c : caches)
+ c->Refresh();
+}
+
+bool RegisteredCacheUnion::HasEntry(u64 title_id, ContentRecordType type) const {
+ return std::any_of(caches.begin(), caches.end(), [title_id, type](const auto& cache) {
+ return cache->HasEntry(title_id, type);
+ });
+}
+
+bool RegisteredCacheUnion::HasEntry(RegisteredCacheEntry entry) const {
+ return HasEntry(entry.title_id, entry.type);
+}
+
+boost::optional<u32> RegisteredCacheUnion::GetEntryVersion(u64 title_id) const {
+ for (const auto& c : caches) {
+ const auto res = c->GetEntryVersion(title_id);
+ if (res != boost::none)
+ return res;
+ }
+
+ return boost::none;
+}
+
+VirtualFile RegisteredCacheUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
+ for (const auto& c : caches) {
+ const auto res = c->GetEntryUnparsed(title_id, type);
+ if (res != nullptr)
+ return res;
+ }
+
+ return nullptr;
+}
+
+VirtualFile RegisteredCacheUnion::GetEntryUnparsed(RegisteredCacheEntry entry) const {
+ return GetEntryUnparsed(entry.title_id, entry.type);
+}
+
+VirtualFile RegisteredCacheUnion::GetEntryRaw(u64 title_id, ContentRecordType type) const {
+ for (const auto& c : caches) {
+ const auto res = c->GetEntryRaw(title_id, type);
+ if (res != nullptr)
+ return res;
+ }
+
+ return nullptr;
+}
+
+VirtualFile RegisteredCacheUnion::GetEntryRaw(RegisteredCacheEntry entry) const {
+ return GetEntryRaw(entry.title_id, entry.type);
+}
+
+std::shared_ptr<NCA> RegisteredCacheUnion::GetEntry(u64 title_id, ContentRecordType type) const {
+ const auto raw = GetEntryRaw(title_id, type);
+ if (raw == nullptr)
+ return nullptr;
+ return std::make_shared<NCA>(raw);
+}
+
+std::shared_ptr<NCA> RegisteredCacheUnion::GetEntry(RegisteredCacheEntry entry) const {
+ return GetEntry(entry.title_id, entry.type);
+}
+
+std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntries() const {
+ std::vector<RegisteredCacheEntry> out;
+ for (const auto& c : caches) {
+ c->IterateAllMetadata<RegisteredCacheEntry>(
+ out,
+ [](const CNMT& c, const ContentRecord& r) {
+ return RegisteredCacheEntry{c.GetTitleID(), r.type};
+ },
+ [](const CNMT& c, const ContentRecord& r) { return true; });
+ }
+ return out;
+}
+
+std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
+ boost::optional<TitleType> title_type, boost::optional<ContentRecordType> record_type,
+ boost::optional<u64> title_id) const {
+ std::vector<RegisteredCacheEntry> out;
+ for (const auto& c : caches) {
+ c->IterateAllMetadata<RegisteredCacheEntry>(
+ out,
+ [](const CNMT& c, const ContentRecord& r) {
+ return RegisteredCacheEntry{c.GetTitleID(), r.type};
+ },
+ [&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
+ if (title_type != boost::none && title_type.get() != c.GetType())
+ return false;
+ if (record_type != boost::none && record_type.get() != r.type)
+ return false;
+ if (title_id != boost::none && title_id.get() != c.GetTitleID())
+ return false;
+ return true;
+ });
+ }
+ return out;
+}
} // namespace FileSys