/* * 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 #include namespace ams::fssrv::impl { StorageInterfaceAdapter::StorageInterfaceAdapter(fs::IStorage *storage) : base_storage(storage) { /* ... */ } StorageInterfaceAdapter::StorageInterfaceAdapter(std::unique_ptr storage) : base_storage(storage.release()) { /* ... */ } StorageInterfaceAdapter::StorageInterfaceAdapter(std::shared_ptr storage) : base_storage(std::move(storage)) { /* ... */ } StorageInterfaceAdapter::~StorageInterfaceAdapter() { /* ... */ } std::optional> StorageInterfaceAdapter::AcquireCacheInvalidationReadLock() { std::optional> lock; if (this->deep_retry_enabled) { lock.emplace(this->invalidation_lock); } return lock; } Result StorageInterfaceAdapter::Read(s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size) { /* TODO: N retries on ResultDataCorrupted, we may want to eventually. */ /* TODO: Deep retry */ R_UNLESS(offset >= 0, fs::ResultInvalidOffset()); R_UNLESS(size >= 0, fs::ResultInvalidSize()); return this->base_storage->Read(offset, buffer.GetPointer(), size); } Result StorageInterfaceAdapter::Write(s64 offset, const ams::sf::InNonSecureBuffer &buffer, s64 size) { /* TODO: N increases thread priority temporarily when writing. We may want to eventually. */ R_UNLESS(offset >= 0, fs::ResultInvalidOffset()); R_UNLESS(size >= 0, fs::ResultInvalidSize()); auto read_lock = this->AcquireCacheInvalidationReadLock(); return this->base_storage->Write(offset, buffer.GetPointer(), size); } Result StorageInterfaceAdapter::Flush() { auto read_lock = this->AcquireCacheInvalidationReadLock(); return this->base_storage->Flush(); } Result StorageInterfaceAdapter::SetSize(s64 size) { R_UNLESS(size >= 0, fs::ResultInvalidSize()); auto read_lock = this->AcquireCacheInvalidationReadLock(); return this->base_storage->SetSize(size); } Result StorageInterfaceAdapter::GetSize(ams::sf::Out out) { auto read_lock = this->AcquireCacheInvalidationReadLock(); return this->base_storage->GetSize(out.GetPointer()); } Result StorageInterfaceAdapter::OperateRange(ams::sf::Out out, s32 op_id, s64 offset, s64 size) { /* N includes this redundant check, so we will too. */ R_UNLESS(out.GetPointer() != nullptr, fs::ResultNullptrArgument()); out->Clear(); if (op_id == static_cast(fs::OperationId::QueryRange)) { auto read_lock = this->AcquireCacheInvalidationReadLock(); fs::StorageQueryRangeInfo info; R_TRY(this->base_storage->OperateRange(&info, sizeof(info), fs::OperationId::QueryRange, offset, size, nullptr, 0)); out->Merge(info); } return ResultSuccess(); } }