diff --git a/libraries/libstratosphere/include/stratosphere/fs.hpp b/libraries/libstratosphere/include/stratosphere/fs.hpp index 176588f..413d23b 100644 --- a/libraries/libstratosphere/include/stratosphere/fs.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs.hpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/fs/common/fs_file_storage.hpp b/libraries/libstratosphere/include/stratosphere/fs/common/fs_file_storage.hpp new file mode 100644 index 0000000..3d8f44e --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/common/fs_file_storage.hpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018-2020 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 +#include +#include + +namespace ams::fs { + + class FileStorage : public IStorage, public impl::Newable { + NON_COPYABLE(FileStorage); + NON_MOVEABLE(FileStorage); + private: + static constexpr s64 InvalidSize = -1; + private: + std::unique_ptr unique_file; + std::shared_ptr shared_file; + fsa::IFile *base_file; + s64 size; + public: + FileStorage(fsa::IFile *f) : unique_file(f), size(InvalidSize) { + this->base_file = this->unique_file.get(); + } + + FileStorage(std::unique_ptr f) : unique_file(std::move(f)), size(InvalidSize) { + this->base_file = this->unique_file.get(); + } + + FileStorage(std::shared_ptr f) : shared_file(f), size(InvalidSize) { + this->base_file = this->shared_file.get(); + } + + virtual ~FileStorage() { /* ... */ } + private: + Result UpdateSize(); + protected: + constexpr FileStorage() : unique_file(), shared_file(), base_file(nullptr), size(InvalidSize) { /* ... */ } + + void SetFile(fs::fsa::IFile *file) { + AMS_ASSERT(file != nullptr); + AMS_ASSERT(this->base_file == nullptr); + this->base_file = file; + } + + void SetFile(std::unique_ptr &&file) { + AMS_ASSERT(file != nullptr); + AMS_ASSERT(this->base_file == nullptr); + AMS_ASSERT(this->unique_file == nullptr); + + this->unique_file = std::move(file); + this->base_file = this->unique_file.get(); + } + public: + virtual Result Read(s64 offset, void *buffer, size_t size) override; + virtual Result Write(s64 offset, const void *buffer, size_t size) override; + virtual Result Flush() override; + virtual Result GetSize(s64 *out_size) override; + virtual Result SetSize(s64 size) override; + virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override; + }; + + class FileStorageBasedFileSystem : public FileStorage { + NON_COPYABLE(FileStorageBasedFileSystem); + NON_MOVEABLE(FileStorageBasedFileSystem); + private: + std::shared_ptr base_file_system; + public: + constexpr FileStorageBasedFileSystem() : FileStorage(), base_file_system(nullptr) { /* ... */ } + + Result Initialize(std::shared_ptr base_file_system, const char *path, fs::OpenMode mode); + }; + + class FileHandleStorage : public IStorage, public impl::Newable { + private: + static constexpr s64 InvalidSize = -1; + private: + FileHandle handle; + bool close_file; + s64 size; + os::Mutex mutex; + public: + constexpr explicit FileHandleStorage(FileHandle handle, bool close_file) : handle(handle), close_file(close_file), size(InvalidSize), mutex(false) { /* ... */ } + constexpr explicit FileHandleStorage(FileHandle handle) : FileHandleStorage(handle, false) { /* ... */ } + + virtual ~FileHandleStorage() override { + if (this->close_file) { + CloseFile(this->handle); + } + } + protected: + Result UpdateSize(); + public: + virtual Result Read(s64 offset, void *buffer, size_t size) override; + virtual Result Write(s64 offset, const void *buffer, size_t size) override; + virtual Result Flush() override; + virtual Result GetSize(s64 *out_size) override; + virtual Result SetSize(s64 size) override; + virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override; + }; + +} diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_file_storage.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_file_storage.hpp deleted file mode 100644 index 3d8f44e..0000000 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_file_storage.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2018-2020 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 -#include -#include - -namespace ams::fs { - - class FileStorage : public IStorage, public impl::Newable { - NON_COPYABLE(FileStorage); - NON_MOVEABLE(FileStorage); - private: - static constexpr s64 InvalidSize = -1; - private: - std::unique_ptr unique_file; - std::shared_ptr shared_file; - fsa::IFile *base_file; - s64 size; - public: - FileStorage(fsa::IFile *f) : unique_file(f), size(InvalidSize) { - this->base_file = this->unique_file.get(); - } - - FileStorage(std::unique_ptr f) : unique_file(std::move(f)), size(InvalidSize) { - this->base_file = this->unique_file.get(); - } - - FileStorage(std::shared_ptr f) : shared_file(f), size(InvalidSize) { - this->base_file = this->shared_file.get(); - } - - virtual ~FileStorage() { /* ... */ } - private: - Result UpdateSize(); - protected: - constexpr FileStorage() : unique_file(), shared_file(), base_file(nullptr), size(InvalidSize) { /* ... */ } - - void SetFile(fs::fsa::IFile *file) { - AMS_ASSERT(file != nullptr); - AMS_ASSERT(this->base_file == nullptr); - this->base_file = file; - } - - void SetFile(std::unique_ptr &&file) { - AMS_ASSERT(file != nullptr); - AMS_ASSERT(this->base_file == nullptr); - AMS_ASSERT(this->unique_file == nullptr); - - this->unique_file = std::move(file); - this->base_file = this->unique_file.get(); - } - public: - virtual Result Read(s64 offset, void *buffer, size_t size) override; - virtual Result Write(s64 offset, const void *buffer, size_t size) override; - virtual Result Flush() override; - virtual Result GetSize(s64 *out_size) override; - virtual Result SetSize(s64 size) override; - virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override; - }; - - class FileStorageBasedFileSystem : public FileStorage { - NON_COPYABLE(FileStorageBasedFileSystem); - NON_MOVEABLE(FileStorageBasedFileSystem); - private: - std::shared_ptr base_file_system; - public: - constexpr FileStorageBasedFileSystem() : FileStorage(), base_file_system(nullptr) { /* ... */ } - - Result Initialize(std::shared_ptr base_file_system, const char *path, fs::OpenMode mode); - }; - - class FileHandleStorage : public IStorage, public impl::Newable { - private: - static constexpr s64 InvalidSize = -1; - private: - FileHandle handle; - bool close_file; - s64 size; - os::Mutex mutex; - public: - constexpr explicit FileHandleStorage(FileHandle handle, bool close_file) : handle(handle), close_file(close_file), size(InvalidSize), mutex(false) { /* ... */ } - constexpr explicit FileHandleStorage(FileHandle handle) : FileHandleStorage(handle, false) { /* ... */ } - - virtual ~FileHandleStorage() override { - if (this->close_file) { - CloseFile(this->handle); - } - } - protected: - Result UpdateSize(); - public: - virtual Result Read(s64 offset, void *buffer, size_t size) override; - virtual Result Write(s64 offset, const void *buffer, size_t size) override; - virtual Result Flush() override; - virtual Result GetSize(s64 *out_size) override; - virtual Result SetSize(s64 size) override; - virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override; - }; - -} diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_submission_package_install_task.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_submission_package_install_task.hpp index 91f8b20..790590c 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_submission_package_install_task.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_submission_package_install_task.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include #include namespace ams::ncm { diff --git a/libraries/libstratosphere/source/fs/common/fs_file_storage.cpp b/libraries/libstratosphere/source/fs/common/fs_file_storage.cpp new file mode 100644 index 0000000..1d6bdfd --- /dev/null +++ b/libraries/libstratosphere/source/fs/common/fs_file_storage.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2018-2020 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 . + */ +#include + +namespace ams::fs { + + Result FileStorage::UpdateSize() { + R_SUCCEED_IF(this->size != InvalidSize); + return this->base_file->GetSize(std::addressof(this->size)); + } + + Result FileStorage::Read(s64 offset, void *buffer, size_t size) { + /* Immediately succeed if there's nothing to read. */ + R_SUCCEED_IF(size == 0); + + /* Validate buffer. */ + R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); + + /* Ensure our size is valid. */ + R_TRY(this->UpdateSize()); + + /* Ensure our access is valid. */ + R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); + + size_t read_size; + return this->base_file->Read(std::addressof(read_size), offset, buffer, size); + } + + Result FileStorage::Write(s64 offset, const void *buffer, size_t size) { + /* Immediately succeed if there's nothing to write. */ + R_SUCCEED_IF(size == 0); + + /* Validate buffer. */ + R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); + + /* Ensure our size is valid. */ + R_TRY(this->UpdateSize()); + + /* Ensure our access is valid. */ + R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); + + return this->base_file->Write(offset, buffer, size, fs::WriteOption()); + } + + Result FileStorage::Flush() { + return this->base_file->Flush(); + } + + Result FileStorage::GetSize(s64 *out_size) { + R_TRY(this->UpdateSize()); + *out_size = this->size; + return ResultSuccess(); + } + + Result FileStorage::SetSize(s64 size) { + this->size = InvalidSize; + return this->base_file->SetSize(size); + } + + Result FileStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { + switch (op_id) { + case OperationId::InvalidateCache: + case OperationId::QueryRange: + if (size == 0) { + if (op_id == OperationId::QueryRange) { + R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); + R_UNLESS(dst_size == sizeof(QueryRangeInfo), fs::ResultInvalidSize()); + reinterpret_cast(dst)->Clear(); + } + return ResultSuccess(); + } + R_TRY(this->UpdateSize()); + R_UNLESS(IStorage::CheckOffsetAndSize(offset, size), fs::ResultOutOfRange()); + return this->base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size); + default: + return fs::ResultUnsupportedOperationInFileStorageA(); + } + } + + Result FileStorageBasedFileSystem::Initialize(std::shared_ptr base_file_system, const char *path, fs::OpenMode mode) { + /* Open the file. */ + std::unique_ptr base_file; + R_TRY(base_file_system->OpenFile(std::addressof(base_file), path, mode)); + + /* Set the file. */ + this->SetFile(std::move(base_file)); + this->base_file_system = std::move(base_file_system); + + return ResultSuccess(); + } + + Result FileHandleStorage::UpdateSize() { + R_SUCCEED_IF(this->size != InvalidSize); + return GetFileSize(std::addressof(this->size), this->handle); + } + + Result FileHandleStorage::Read(s64 offset, void *buffer, size_t size) { + /* Lock the mutex. */ + std::scoped_lock lk(this->mutex); + + /* Immediately succeed if there's nothing to read. */ + R_SUCCEED_IF(size == 0); + + /* Validate buffer. */ + R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); + + /* Ensure our size is valid. */ + R_TRY(this->UpdateSize()); + + /* Ensure our access is valid. */ + R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); + + return ReadFile(this->handle, offset, buffer, size, fs::ReadOption()); + } + + Result FileHandleStorage::Write(s64 offset, const void *buffer, size_t size) { + /* Lock the mutex. */ + std::scoped_lock lk(this->mutex); + + /* Immediately succeed if there's nothing to write. */ + R_SUCCEED_IF(size == 0); + + /* Validate buffer. */ + R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); + + /* Ensure our size is valid. */ + R_TRY(this->UpdateSize()); + + /* Ensure our access is valid. */ + R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); + + return WriteFile(this->handle, offset, buffer, size, fs::WriteOption()); + } + + Result FileHandleStorage::Flush() { + return FlushFile(this->handle); + } + + Result FileHandleStorage::GetSize(s64 *out_size) { + R_TRY(this->UpdateSize()); + *out_size = this->size; + return ResultSuccess(); + } + + Result FileHandleStorage::SetSize(s64 size) { + this->size = InvalidSize; + return SetFileSize(this->handle, size); + } + + Result FileHandleStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { + switch (op_id) { + case OperationId::QueryRange: + /* Validate buffer and size. */ + R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); + R_UNLESS(dst_size == sizeof(QueryRangeInfo), fs::ResultInvalidSize()); + + return QueryRange(static_cast(dst), this->handle, offset, size); + default: + return fs::ResultUnsupportedOperationInFileStorageB(); + } + } + +} diff --git a/libraries/libstratosphere/source/fs/fs_file_storage.cpp b/libraries/libstratosphere/source/fs/fs_file_storage.cpp deleted file mode 100644 index d0401bb..0000000 --- a/libraries/libstratosphere/source/fs/fs_file_storage.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2018-2020 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 . - */ -#include - -namespace ams::fs { - - Result FileStorage::UpdateSize() { - R_SUCCEED_IF(this->size != InvalidSize); - return this->base_file->GetSize(&this->size); - } - - Result FileStorage::Read(s64 offset, void *buffer, size_t size) { - /* Immediately succeed if there's nothing to read. */ - R_SUCCEED_IF(size == 0); - - /* Validate buffer. */ - R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); - - /* Ensure our size is valid. */ - R_TRY(this->UpdateSize()); - - /* Ensure our access is valid. */ - R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); - - size_t read_size; - return this->base_file->Read(&read_size, offset, buffer, size); - } - - Result FileStorage::Write(s64 offset, const void *buffer, size_t size) { - /* Immediately succeed if there's nothing to write. */ - R_SUCCEED_IF(size == 0); - - /* Validate buffer. */ - R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); - - /* Ensure our size is valid. */ - R_TRY(this->UpdateSize()); - - /* Ensure our access is valid. */ - R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); - - return this->base_file->Write(offset, buffer, size, fs::WriteOption()); - } - - Result FileStorage::Flush() { - return this->base_file->Flush(); - } - - Result FileStorage::GetSize(s64 *out_size) { - R_TRY(this->UpdateSize()); - *out_size = this->size; - return ResultSuccess(); - } - - Result FileStorage::SetSize(s64 size) { - this->size = InvalidSize; - return this->base_file->SetSize(size); - } - - Result FileStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { - switch (op_id) { - case OperationId::InvalidateCache: - case OperationId::QueryRange: - if (size == 0) { - if (op_id == OperationId::QueryRange) { - R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); - R_UNLESS(dst_size == sizeof(QueryRangeInfo), fs::ResultInvalidSize()); - reinterpret_cast(dst)->Clear(); - } - return ResultSuccess(); - } - R_TRY(this->UpdateSize()); - R_UNLESS(IStorage::CheckOffsetAndSize(offset, size), fs::ResultOutOfRange()); - return this->base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size); - default: - return fs::ResultUnsupportedOperationInFileStorageA(); - } - } - - Result FileStorageBasedFileSystem::Initialize(std::shared_ptr base_file_system, const char *path, fs::OpenMode mode) { - /* Open the file. */ - std::unique_ptr base_file; - R_TRY(base_file_system->OpenFile(std::addressof(base_file), path, mode)); - - /* Set the file. */ - this->SetFile(std::move(base_file)); - this->base_file_system = std::move(base_file_system); - - return ResultSuccess(); - } - - Result FileHandleStorage::UpdateSize() { - R_SUCCEED_IF(this->size != InvalidSize); - return GetFileSize(std::addressof(this->size), this->handle); - } - - Result FileHandleStorage::Read(s64 offset, void *buffer, size_t size) { - /* Lock the mutex. */ - std::scoped_lock lk(this->mutex); - - /* Immediately succeed if there's nothing to read. */ - R_SUCCEED_IF(size == 0); - - /* Validate buffer. */ - R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); - - /* Ensure our size is valid. */ - R_TRY(this->UpdateSize()); - - /* Ensure our access is valid. */ - R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); - - return ReadFile(this->handle, offset, buffer, size, fs::ReadOption()); - } - - Result FileHandleStorage::Write(s64 offset, const void *buffer, size_t size) { - /* Lock the mutex. */ - std::scoped_lock lk(this->mutex); - - /* Immediately succeed if there's nothing to write. */ - R_SUCCEED_IF(size == 0); - - /* Validate buffer. */ - R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); - - /* Ensure our size is valid. */ - R_TRY(this->UpdateSize()); - - /* Ensure our access is valid. */ - R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange()); - - return WriteFile(this->handle, offset, buffer, size, fs::WriteOption()); - } - - Result FileHandleStorage::Flush() { - return FlushFile(this->handle); - } - - Result FileHandleStorage::GetSize(s64 *out_size) { - R_TRY(this->UpdateSize()); - *out_size = this->size; - return ResultSuccess(); - } - - Result FileHandleStorage::SetSize(s64 size) { - this->size = InvalidSize; - return SetFileSize(this->handle, size); - } - - Result FileHandleStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { - switch (op_id) { - case OperationId::QueryRange: - /* Validate buffer and size. */ - R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); - R_UNLESS(dst_size == sizeof(QueryRangeInfo), fs::ResultInvalidSize()); - - return QueryRange(static_cast(dst), this->handle, offset, size); - default: - return fs::ResultUnsupportedOperationInFileStorageB(); - } - } - -}