diff --git a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp index fe6e3339e..19dbe5c5e 100644 --- a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp @@ -123,6 +123,8 @@ namespace ams::fssystem { AMS_UNUSED(size); R_THROW(fs::ResultUnsupportedSetSizeForAesCtrCounterExtendedStorage()); } + + Result GetEntryList(Entry *out_entries, s32 *out_entry_count, s32 entry_count, s64 offset, s64 size); private: Result Initialize(IAllocator *allocator, const void *key, size_t key_size, u32 secure_value, fs::SubStorage data_storage, fs::SubStorage table_storage); }; diff --git a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp index 88d1bb464..c5337f151 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp @@ -110,6 +110,66 @@ namespace ams::fssystem { } } + Result AesCtrCounterExtendedStorage::GetEntryList(Entry *out_entries, s32 *out_entry_count, s32 entry_count, s64 offset, s64 size) { + /* Validate pre-conditions. */ + AMS_ASSERT(offset >= 0); + AMS_ASSERT(size >= 0); + AMS_ASSERT(this->IsInitialized()); + + /* Clear the out count. */ + R_UNLESS(out_entry_count != nullptr, fs::ResultNullptrArgument()); + *out_entry_count = 0; + + /* Succeed if there's no range. */ + R_SUCCEED_IF(size == 0); + + /* If we have an output array, we need it to be non-null. */ + R_UNLESS(out_entries != nullptr || entry_count == 0, fs::ResultNullptrArgument()); + + /* Check that our range is valid. */ + BucketTree::Offsets table_offsets; + R_TRY(m_table.GetOffsets(std::addressof(table_offsets))); + + R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange()); + + /* Find the offset in our tree. */ + BucketTree::Visitor visitor; + R_TRY(m_table.Find(std::addressof(visitor), offset)); + { + const auto entry_offset = visitor.Get()->GetOffset(); + R_UNLESS(0 <= entry_offset && table_offsets.IsInclude(entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset()); + } + + /* Prepare to loop over entries. */ + const auto end_offset = offset + static_cast(size); + s32 count = 0; + + auto cur_entry = *visitor.Get(); + while (cur_entry.GetOffset() < end_offset) { + /* Try to write the entry to the out list */ + if (entry_count != 0) { + if (count >= entry_count) { + break; + } + std::memcpy(out_entries + count, std::addressof(cur_entry), sizeof(Entry)); + } + + count++; + + /* Advance. */ + if (visitor.CanMoveNext()) { + R_TRY(visitor.MoveNext()); + cur_entry = *visitor.Get(); + } else { + break; + } + } + + /* Write the output count. */ + *out_entry_count = count; + R_SUCCEED(); + } + Result AesCtrCounterExtendedStorage::Read(s64 offset, void *buffer, size_t size) { /* Validate preconditions. */ AMS_ASSERT(offset >= 0); @@ -126,7 +186,7 @@ namespace ams::fssystem { BucketTree::Offsets table_offsets; R_TRY(m_table.GetOffsets(std::addressof(table_offsets))); - R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange()); + R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange()); /* Read the data. */ R_TRY(m_data_storage.Read(offset, buffer, size));