From 0fbf007bcf7831a075bffd6b4e942fc7609b911a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 28 Mar 2022 00:54:10 -0700 Subject: [PATCH] fs: fixup all OperateRange implementations --- .../include/stratosphere/fs.hpp | 1 + .../fs/fs_read_only_filesystem.hpp | 7 +++--- .../fs_storage_service_object_adapter.hpp | 9 ++++--- .../libstratosphere/source/fs/fs_bis.cpp | 3 +-- .../libstratosphere/source/fs/fs_data.cpp | 3 +-- .../source/fs/fs_romfs_filesystem.cpp | 5 ++-- .../fssystem/fssystem_aes_ctr_storage.cpp | 25 +++++++++++-------- .../fssystem/fssystem_buffered_storage.cpp | 5 +--- .../fssystem/fssystem_indirect_storage.cpp | 5 ++++ .../fssystem_partition_file_system.cpp | 23 +++++++++++------ .../fssystem/fssystem_romfs_filesystem.cpp | 15 ++++++----- 11 files changed, 60 insertions(+), 41 deletions(-) rename libraries/libstratosphere/{source => include/stratosphere}/fs/impl/fs_storage_service_object_adapter.hpp (91%) diff --git a/libraries/libstratosphere/include/stratosphere/fs.hpp b/libraries/libstratosphere/include/stratosphere/fs.hpp index 544f1c4a5..7aafab832 100644 --- a/libraries/libstratosphere/include/stratosphere/fs.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs.hpp @@ -65,4 +65,5 @@ #include #include #include +#include #include diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp index 144ed0097..9b8743332 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp @@ -156,18 +156,17 @@ namespace ams::fs { } virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override final { - AMS_UNUSED(out, path); - R_THROW(fs::ResultUnsupportedCommitProvisionallyForReadOnlyFileSystem()); + R_RETURN(m_base_fs->GetFreeSpaceSize(out, path)); } virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override final { AMS_UNUSED(out, path); - R_THROW(fs::ResultUnsupportedCommitProvisionallyForReadOnlyFileSystem()); + R_THROW(fs::ResultUnsupportedGetTotalSpaceSizeForReadOnlyFileSystem()); } virtual Result DoCommitProvisionally(s64 counter) override final { AMS_UNUSED(counter); - R_THROW(fs::ResultUnsupportedGetTotalSpaceSizeForReadOnlyFileSystem()); + R_THROW(fs::ResultUnsupportedCommitProvisionallyForReadOnlyFileSystem()); } }; diff --git a/libraries/libstratosphere/source/fs/impl/fs_storage_service_object_adapter.hpp b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_storage_service_object_adapter.hpp similarity index 91% rename from libraries/libstratosphere/source/fs/impl/fs_storage_service_object_adapter.hpp rename to libraries/libstratosphere/include/stratosphere/fs/impl/fs_storage_service_object_adapter.hpp index fbdfd729b..66d95124a 100644 --- a/libraries/libstratosphere/source/fs/impl/fs_storage_service_object_adapter.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_storage_service_object_adapter.hpp @@ -14,17 +14,20 @@ * along with this program. If not, see . */ #pragma once -#include +#include +#include +#include namespace ams::fs::impl { + template class StorageServiceObjectAdapter : public ::ams::fs::impl::Newable, public ::ams::fs::IStorage { NON_COPYABLE(StorageServiceObjectAdapter); NON_MOVEABLE(StorageServiceObjectAdapter); private: - sf::SharedPointer m_x; + sf::SharedPointer m_x; public: - explicit StorageServiceObjectAdapter(sf::SharedPointer &&o) : m_x(o) { /* ... */} + explicit StorageServiceObjectAdapter(sf::SharedPointer &&o) : m_x(o) { /* ... */} virtual ~StorageServiceObjectAdapter() { /* ... */ } public: virtual Result Read(s64 offset, void *buffer, size_t size) override final { diff --git a/libraries/libstratosphere/source/fs/fs_bis.cpp b/libraries/libstratosphere/source/fs/fs_bis.cpp index 969df0527..8aba6ffff 100644 --- a/libraries/libstratosphere/source/fs/fs_bis.cpp +++ b/libraries/libstratosphere/source/fs/fs_bis.cpp @@ -16,7 +16,6 @@ #include #include "fsa/fs_mount_utils.hpp" #include "impl/fs_file_system_service_object_adapter.hpp" -#include "impl/fs_storage_service_object_adapter.hpp" #include "impl/fs_file_system_proxy_service_object.hpp" namespace ams::fs { @@ -121,7 +120,7 @@ namespace ams::fs { AMS_FS_R_TRY(fsp->OpenBisStorage(std::addressof(s), static_cast(id))); /* Allocate a new storage wrapper. */ - auto storage = std::make_unique(std::move(s)); + auto storage = std::make_unique>(std::move(s)); AMS_FS_R_UNLESS(storage != nullptr, fs::ResultAllocationMemoryFailedInBisC()); *out = std::move(storage); diff --git a/libraries/libstratosphere/source/fs/fs_data.cpp b/libraries/libstratosphere/source/fs/fs_data.cpp index c6df940dc..74218d888 100644 --- a/libraries/libstratosphere/source/fs/fs_data.cpp +++ b/libraries/libstratosphere/source/fs/fs_data.cpp @@ -16,7 +16,6 @@ #include #include "fsa/fs_mount_utils.hpp" #include "impl/fs_file_system_proxy_service_object.hpp" -#include "impl/fs_storage_service_object_adapter.hpp" namespace ams::fs::impl { @@ -35,7 +34,7 @@ namespace ams::fs::impl { sf::SharedPointer s; AMS_FS_R_TRY(OpenDataStorageByDataIdImpl(std::addressof(s), data_id, storage_id)); - auto storage = std::make_unique(std::move(s)); + auto storage = std::make_unique>(std::move(s)); R_UNLESS(storage != nullptr, fs::ResultAllocationMemoryFailedInDataA()); *out = std::move(storage); diff --git a/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp b/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp index a52b57144..22c5bd4d2 100644 --- a/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp +++ b/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp @@ -232,10 +232,11 @@ namespace ams::fs { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { switch (op_id) { case OperationId::Invalidate: + R_RETURN(this->GetStorage()->OperateRange(fs::OperationId::Invalidate, 0, std::numeric_limits::max())); case OperationId::QueryRange: { - R_UNLESS(offset >= 0, fs::ResultOutOfRange()); - R_UNLESS(this->GetSize() >= 0, fs::ResultOutOfRange()); + R_UNLESS(offset >= 0, fs::ResultInvalidOffset()); + R_UNLESS(this->GetSize() >= offset, fs::ResultOutOfRange()); auto operate_size = size; if (offset + operate_size > this->GetSize() || offset + operate_size < offset) { diff --git a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_storage.cpp index 06e7275ba..2594afc04 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_storage.cpp @@ -145,22 +145,25 @@ namespace ams::fssystem { template Result AesCtrStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { - /* Handle the zero size case. */ - if (size == 0) { - if (op_id == fs::OperationId::QueryRange) { - R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); - R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize()); + /* If operation isn't invalidate, special case. */ + if (op_id != fs::OperationId::Invalidate) { + /* Handle the zero-size case. */ + if (size == 0) { + if (op_id == fs::OperationId::QueryRange) { + R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); + R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize()); - reinterpret_cast(dst)->Clear(); + reinterpret_cast(dst)->Clear(); + } + + R_SUCCEED(); } - R_SUCCEED(); + /* Ensure alignment. */ + R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidArgument()); + R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidArgument()); } - /* Ensure alignment. */ - R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidArgument()); - R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidArgument()); - switch (op_id) { case fs::OperationId::QueryRange: { diff --git a/libraries/libstratosphere/source/fssystem/fssystem_buffered_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_buffered_storage.cpp index ba36fd7bd..f612a8eed 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_buffered_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_buffered_storage.cpp @@ -722,10 +722,7 @@ namespace ams::fssystem { /* Invalidate caches, if we should. */ if (op_id == fs::OperationId::Invalidate) { - SharedCache cache(this); - while (cache.AcquireNextOverlappedCache(offset, size)) { - cache.Invalidate(); - } + this->InvalidateCaches(); } R_RETURN(m_base_storage.OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); diff --git a/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp index 47754b311..32995e761 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp @@ -122,6 +122,11 @@ namespace ams::fssystem { } Result IndirectStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { + /* Validate pre-conditions. */ + AMS_ASSERT(offset >= 0); + AMS_ASSERT(size >= 0); + AMS_ASSERT(this->IsInitialized()); + switch (op_id) { case fs::OperationId::Invalidate: { diff --git a/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp b/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp index 46e83f49f..1cb74ff1d 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp @@ -90,24 +90,33 @@ namespace ams::fssystem { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final { /* Validate preconditions for operation. */ + s64 operate_offset; + s64 operate_size; switch (op_id) { case fs::OperationId::Invalidate: R_UNLESS((m_mode & fs::OpenMode_Read) != 0, fs::ResultReadNotPermitted()); R_UNLESS((m_mode & fs::OpenMode_Write) == 0, fs::ResultUnsupportedOperateRangeForPartitionFile()); + + /* Set offset/size. */ + operate_offset = 0; + operate_size = std::numeric_limits::max(); break; case fs::OperationId::QueryRange: + /* Validate offset and size. */ + R_UNLESS(offset >= 0, fs::ResultOutOfRange()); + R_UNLESS(offset <= static_cast(m_partition_entry->size), fs::ResultOutOfRange()); + R_UNLESS(static_cast(offset + size) <= static_cast(m_partition_entry->size), fs::ResultInvalidSize()); + R_UNLESS(static_cast(offset + size) >= offset, fs::ResultInvalidSize()); + + /* Set offset/size. */ + operate_offset = m_parent->m_meta_data_size + m_partition_entry->offset + offset; + operate_size = size; break; default: R_THROW(fs::ResultUnsupportedOperateRangeForPartitionFile()); } - /* Validate offset and size. */ - R_UNLESS(offset >= 0, fs::ResultOutOfRange()); - R_UNLESS(offset <= static_cast(m_partition_entry->size), fs::ResultOutOfRange()); - R_UNLESS(static_cast(offset + size) <= static_cast(m_partition_entry->size), fs::ResultInvalidSize()); - R_UNLESS(static_cast(offset + size) >= offset, fs::ResultInvalidSize()); - - R_RETURN(m_parent->m_base_storage->OperateRange(dst, dst_size, op_id, m_parent->m_meta_data_size + m_partition_entry->offset + offset, size, src, src_size)); + R_RETURN(m_parent->m_base_storage->OperateRange(dst, dst_size, op_id, operate_offset, operate_size, src, src_size)); } public: virtual sf::cmif::DomainObjectId GetDomainObjectId() const override { diff --git a/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp b/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp index 061e518f9..57a1c6556 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp @@ -77,21 +77,24 @@ namespace ams::fssystem { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { switch (op_id) { case fs::OperationId::Invalidate: + { + R_RETURN(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result { + R_RETURN(m_parent->GetBaseStorage()->OperateRange(fs::OperationId::Invalidate, 0, std::numeric_limits::max())); + }, AMS_CURRENT_FUNCTION_NAME)); + } case fs::OperationId::QueryRange: { - R_UNLESS(offset >= 0, fs::ResultOutOfRange()); - R_UNLESS(this->GetSize() >= 0, fs::ResultOutOfRange()); + R_UNLESS(offset >= 0, fs::ResultInvalidOffset()); + R_UNLESS(this->GetSize() >= offset, fs::ResultOutOfRange()); auto operate_size = size; if (offset + operate_size > this->GetSize() || offset + operate_size < offset) { operate_size = this->GetSize() - offset; } - R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result { - R_TRY(m_parent->GetBaseStorage()->OperateRange(dst, dst_size, op_id, m_start + offset, operate_size, src, src_size)); - R_SUCCEED(); + R_RETURN(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result { + R_RETURN(m_parent->GetBaseStorage()->OperateRange(dst, dst_size, op_id, m_start + offset, operate_size, src, src_size)); }, AMS_CURRENT_FUNCTION_NAME)); - R_SUCCEED(); } default: R_THROW(fs::ResultUnsupportedOperateRangeForRomFsFile());