|
|
@ -127,6 +127,156 @@ std::vector<ContentProviderEntry> ContentProvider::ListEntries() const {
|
|
|
|
return ListEntriesFilter(std::nullopt, std::nullopt, std::nullopt);
|
|
|
|
return ListEntriesFilter(std::nullopt, std::nullopt, std::nullopt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PlaceholderCache::PlaceholderCache(VirtualDir dir_) : dir(std::move(dir_)) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PlaceholderCache::Create(const NcaID& id, u64 size) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(id, false, true, false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dir->GetFileRelative(path) != nullptr) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Core::Crypto::SHA256Hash hash{};
|
|
|
|
|
|
|
|
mbedtls_sha256(id.data(), id.size(), hash.data(), 0);
|
|
|
|
|
|
|
|
const auto dirname = fmt::format("000000{:02X}", hash[0]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dir2 == nullptr)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto file = dir2->CreateFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (file == nullptr)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return file->Resize(size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PlaceholderCache::Delete(const NcaID& id) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(id, false, true, false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dir->GetFileRelative(path) == nullptr) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Core::Crypto::SHA256Hash hash{};
|
|
|
|
|
|
|
|
mbedtls_sha256(id.data(), id.size(), hash.data(), 0);
|
|
|
|
|
|
|
|
const auto dirname = fmt::format("000000{:02X}", hash[0]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto res = dir2->DeleteFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PlaceholderCache::Exists(const NcaID& id) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(id, false, true, false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return dir->GetFileRelative(path) != nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PlaceholderCache::Write(const NcaID& id, u64 offset, const std::vector<u8>& data) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(id, false, true, false);
|
|
|
|
|
|
|
|
const auto file = dir->GetFileRelative(path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (file == nullptr)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return file->WriteBytes(data, offset) == data.size();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PlaceholderCache::Register(RegisteredCache* cache, const NcaID& placeholder,
|
|
|
|
|
|
|
|
const NcaID& install) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(placeholder, false, true, false);
|
|
|
|
|
|
|
|
const auto file = dir->GetFileRelative(path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (file == nullptr)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto res = cache->RawInstallNCA(NCA{file}, &VfsRawCopy, false, install);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (res != InstallResult::Success)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Delete(placeholder);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PlaceholderCache::CleanAll() const {
|
|
|
|
|
|
|
|
return dir->GetParentDirectory()->CleanSubdirectoryRecursive(dir->GetName());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::optional<std::array<u8, 0x10>> PlaceholderCache::GetRightsID(const NcaID& id) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(id, false, true, false);
|
|
|
|
|
|
|
|
const auto file = dir->GetFileRelative(path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (file == nullptr)
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NCA nca{file};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nca.GetStatus() != Loader::ResultStatus::Success &&
|
|
|
|
|
|
|
|
nca.GetStatus() != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto rights_id = nca.GetRightsId();
|
|
|
|
|
|
|
|
if (rights_id == NcaID{})
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return rights_id;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u64 PlaceholderCache::Size(const NcaID& id) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(id, false, true, false);
|
|
|
|
|
|
|
|
const auto file = dir->GetFileRelative(path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (file == nullptr)
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return file->GetSize();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PlaceholderCache::SetSize(const NcaID& id, u64 new_size) const {
|
|
|
|
|
|
|
|
const auto path = GetRelativePathFromNcaID(id, false, true, false);
|
|
|
|
|
|
|
|
const auto file = dir->GetFileRelative(path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (file == nullptr)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return file->Resize(new_size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<NcaID> PlaceholderCache::List() const {
|
|
|
|
|
|
|
|
std::vector<NcaID> out;
|
|
|
|
|
|
|
|
for (const auto& sdir : dir->GetSubdirectories()) {
|
|
|
|
|
|
|
|
for (const auto& file : sdir->GetFiles()) {
|
|
|
|
|
|
|
|
const auto name = file->GetName();
|
|
|
|
|
|
|
|
if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' &&
|
|
|
|
|
|
|
|
name[35] == 'a') {
|
|
|
|
|
|
|
|
out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NcaID PlaceholderCache::Generate() {
|
|
|
|
|
|
|
|
std::random_device device;
|
|
|
|
|
|
|
|
std::mt19937 gen(device());
|
|
|
|
|
|
|
|
std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NcaID out{};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto v1 = distribution(gen);
|
|
|
|
|
|
|
|
const auto v2 = distribution(gen);
|
|
|
|
|
|
|
|
std::memcpy(out.data(), &v1, sizeof(u64));
|
|
|
|
|
|
|
|
std::memcpy(out.data() + sizeof(u64), &v2, sizeof(u64));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
|
|
|
|
VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
|
|
|
|
std::string_view path) const {
|
|
|
|
std::string_view path) const {
|
|
|
|
const auto file = dir->GetFileRelative(path);
|
|
|
|
const auto file = dir->GetFileRelative(path);
|
|
|
|