diff --git a/libraries/libstratosphere/include/stratosphere/fs.hpp b/libraries/libstratosphere/include/stratosphere/fs.hpp index 544f1c4..7aafab8 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 144ed00..9b87433 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 @@ } 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/include/stratosphere/fs/impl/fs_storage_service_object_adapter.hpp b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_storage_service_object_adapter.hpp new file mode 100644 index 0000000..66d9512 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_storage_service_object_adapter.hpp @@ -0,0 +1,76 @@ +/* + * 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 . + */ +#pragma once +#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; + public: + explicit StorageServiceObjectAdapter(sf::SharedPointer &&o) : m_x(o) { /* ... */} + virtual ~StorageServiceObjectAdapter() { /* ... */ } + public: + virtual Result Read(s64 offset, void *buffer, size_t size) override final { + R_RETURN(m_x->Read(offset, sf::OutNonSecureBuffer(buffer, size), static_cast(size))); + } + + virtual Result GetSize(s64 *out) override final { + R_RETURN(m_x->GetSize(out)); + } + + virtual Result Flush() override final { + R_RETURN(m_x->Flush()); + } + + virtual Result Write(s64 offset, const void *buffer, size_t size) override final { + R_RETURN(m_x->Write(offset, sf::InNonSecureBuffer(buffer, size), static_cast(size))); + } + + virtual Result SetSize(s64 size) override final { + R_RETURN(m_x->SetSize(size)); + } + + virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final { + AMS_UNUSED(src, src_size); + switch (op_id) { + case OperationId::Invalidate: + { + fs::QueryRangeInfo dummy_range_info; + R_RETURN(m_x->OperateRange(std::addressof(dummy_range_info), static_cast(op_id), offset, size)); + } + case OperationId::QueryRange: + { + R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); + R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize()); + + R_RETURN(m_x->OperateRange(reinterpret_cast(dst), static_cast(op_id), offset, size)); + } + default: + { + R_THROW(fs::ResultUnsupportedOperateRangeForStorageServiceObjectAdapter()); + } + } + } + }; + +} diff --git a/libraries/libstratosphere/source/fs/fs_bis.cpp b/libraries/libstratosphere/source/fs/fs_bis.cpp index 969df05..8aba6ff 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 @@ 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 c6df940..74218d8 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 @@ 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 a52b571..22c5bd4 100644 --- a/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp +++ b/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp @@ -232,10 +232,11 @@ 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/fs/impl/fs_storage_service_object_adapter.hpp b/libraries/libstratosphere/source/fs/impl/fs_storage_service_object_adapter.hpp deleted file mode 100644 index fbdfd72..0000000 --- a/libraries/libstratosphere/source/fs/impl/fs_storage_service_object_adapter.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 . - */ -#pragma once -#include - -namespace ams::fs::impl { - - class StorageServiceObjectAdapter : public ::ams::fs::impl::Newable, public ::ams::fs::IStorage { - NON_COPYABLE(StorageServiceObjectAdapter); - NON_MOVEABLE(StorageServiceObjectAdapter); - private: - sf::SharedPointer m_x; - public: - explicit StorageServiceObjectAdapter(sf::SharedPointer &&o) : m_x(o) { /* ... */} - virtual ~StorageServiceObjectAdapter() { /* ... */ } - public: - virtual Result Read(s64 offset, void *buffer, size_t size) override final { - R_RETURN(m_x->Read(offset, sf::OutNonSecureBuffer(buffer, size), static_cast(size))); - } - - virtual Result GetSize(s64 *out) override final { - R_RETURN(m_x->GetSize(out)); - } - - virtual Result Flush() override final { - R_RETURN(m_x->Flush()); - } - - virtual Result Write(s64 offset, const void *buffer, size_t size) override final { - R_RETURN(m_x->Write(offset, sf::InNonSecureBuffer(buffer, size), static_cast(size))); - } - - virtual Result SetSize(s64 size) override final { - R_RETURN(m_x->SetSize(size)); - } - - virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final { - AMS_UNUSED(src, src_size); - switch (op_id) { - case OperationId::Invalidate: - { - fs::QueryRangeInfo dummy_range_info; - R_RETURN(m_x->OperateRange(std::addressof(dummy_range_info), static_cast(op_id), offset, size)); - } - case OperationId::QueryRange: - { - R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); - R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize()); - - R_RETURN(m_x->OperateRange(reinterpret_cast(dst), static_cast(op_id), offset, size)); - } - default: - { - R_THROW(fs::ResultUnsupportedOperateRangeForStorageServiceObjectAdapter()); - } - } - } - }; - -} diff --git a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_storage.cpp index 06e7275..2594afc 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 @@ 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 ba36fd7..f612a8e 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_buffered_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_buffered_storage.cpp @@ -722,10 +722,7 @@ /* 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 47754b3..32995e7 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp @@ -122,6 +122,11 @@ } 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 46e83f4..1cb74ff 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 @@ 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 061e518..57a1c65 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp @@ -77,21 +77,24 @@ 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());