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;
+};