diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_file_storage.cpp b/stratosphere/ams_mitm/source/fs_mitm/fs_file_storage.cpp new file mode 100644 index 000000000..f4e154f7d --- /dev/null +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_file_storage.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018-2019 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 +#include + +#include "../utils.hpp" +#include "fs_file_storage.hpp" + +Result FileStorage::UpdateSize() { + if (this->size == InvalidSize) { + return this->file->GetSize(&this->size); + } + return ResultSuccess; +} + +Result FileStorage::Read(void *buffer, size_t size, u64 offset) { + Result rc; + u64 read_size; + + if (size == 0) { + return ResultSuccess; + } + if (buffer == nullptr) { + return ResultFsNullptrArgument; + } + if (R_FAILED((rc = this->UpdateSize()))) { + return rc; + } + if (!IStorage::IsRangeValid(offset, size, this->size)) { + return ResultFsOutOfRange; + } + + return this->file->Read(&read_size, offset, buffer, size); +} + +Result FileStorage::Write(void *buffer, size_t size, u64 offset) { + Result rc; + + if (size == 0) { + return ResultSuccess; + } + if (buffer == nullptr) { + return ResultFsNullptrArgument; + } + if (R_FAILED((rc = this->UpdateSize()))) { + return rc; + } + if (!IStorage::IsRangeValid(offset, size, this->size)) { + return ResultFsOutOfRange; + } + + return this->file->Write(offset, buffer, size); +} + +Result FileStorage::Flush() { + return this->file->Flush(); +} + +Result FileStorage::GetSize(u64 *out_size) { + Result rc = this->UpdateSize(); + if (R_FAILED(rc)) { + return rc; + } + *out_size = this->size; + return ResultSuccess; +} + +Result FileStorage::SetSize(u64 size) { + this->size = InvalidSize; + return this->file->SetSize(size); +} + +Result FileStorage::OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) { + Result rc; + + switch (operation_type) { + case 2: /* TODO: OperationType_Invalidate */ + case 3: /* TODO: OperationType_Query */ + if (size == 0) { + if (operation_type == 3) { + if (out_range_info == nullptr) { + return ResultFsNullptrArgument; + } + /* N checks for size == sizeof(*out_range_info) here, but that's because their wrapper api is bad. */ + std::memset(out_range_info, 0, sizeof(*out_range_info)); + } + return ResultSuccess; + } + if (R_FAILED((rc = this->UpdateSize()))) { + return rc; + } + /* N checks for positivity + signed overflow on offset/size here, but we're using unsigned types... */ + return this->file->OperateRange(operation_type, offset, size, out_range_info); + default: + return ResultFsUnsupportedOperation; + } +} \ No newline at end of file diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_file_storage.hpp b/stratosphere/ams_mitm/source/fs_mitm/fs_file_storage.hpp new file mode 100644 index 000000000..6b21383e4 --- /dev/null +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_file_storage.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018-2019 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 "fs_shim.h" + +#include "../debug.hpp" +#include "fs_istorage.hpp" +#include "fs_ifile.hpp" + +class FileStorage : public IStorage { + public: + static constexpr u64 InvalidSize = UINT64_MAX; + private: + std::shared_ptr base_file; + IFile *file; + u64 size; + public: + FileStorage(IFile *f) : base_file(f) { + this->file = this->base_file.get(); + this->size = InvalidSize; + }; + FileStorage(std::shared_ptr f) : base_file(f) { + this->file = this->base_file.get(); + this->size = InvalidSize; + }; + virtual ~FileStorage() { + /* ... */ + }; + protected: + Result UpdateSize(); + public: + virtual Result Read(void *buffer, size_t size, u64 offset) override; + virtual Result Write(void *buffer, size_t size, u64 offset) override; + virtual Result Flush() override; + virtual Result GetSize(u64 *out_size) override; + virtual Result SetSize(u64 size) override; + virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override; +};