/*
* 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();
}
}