diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index 99f2b19876..79c478f980 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -446,6 +446,7 @@
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index 189b7d2088..d3b4d3be27 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -1404,6 +1404,9 @@
IOS\FS
+
+ IOS\FS
+
IOS\ES
diff --git a/Source/Core/Core/IOS/FS/FileSystem.h b/Source/Core/Core/IOS/FS/FileSystem.h
new file mode 100644
index 0000000000..6607c9ab02
--- /dev/null
+++ b/Source/Core/Core/IOS/FS/FileSystem.h
@@ -0,0 +1,173 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+#include
+
+#include "Common/CommonTypes.h"
+#include "Common/Result.h"
+
+class PointerWrap;
+
+namespace IOS::HLE::FS
+{
+enum class ResultCode
+{
+ Success,
+ Invalid,
+ AccessDenied,
+ SuperblockWriteFailed,
+ SuperblockInitFailed,
+ AlreadyExists,
+ NotFound,
+ FstFull,
+ NoFreeSpace,
+ NoFreeHandle,
+ TooManyPathComponents,
+ InUse,
+ BadBlock,
+ EccError,
+ CriticalEccError,
+ FileNotEmpty,
+ CheckFailed,
+ UnknownError,
+ ShortRead,
+};
+
+template
+using Result = Common::Result;
+
+using Uid = u32;
+using Gid = u16;
+using Fd = u32;
+
+enum class Mode : u8
+{
+ None = 0,
+ Read = 1,
+ Write = 2,
+ ReadWrite = 3,
+};
+
+enum class SeekMode : u32
+{
+ Set = 0,
+ Current = 1,
+ End = 2,
+};
+
+using FileAttribute = u8;
+
+struct Metadata
+{
+ Uid uid;
+ Gid gid;
+ FileAttribute attribute;
+ Mode owner_mode, group_mode, other_mode;
+ bool is_file;
+ u32 size;
+ u16 fst_index;
+};
+
+struct NandStats
+{
+ u32 cluster_size;
+ u32 free_clusters;
+ u32 used_clusters;
+ u32 bad_clusters;
+ u32 reserved_clusters;
+ u32 free_inodes;
+ u32 used_inodes;
+};
+
+struct DirectoryStats
+{
+ u32 used_clusters;
+ u32 used_inodes;
+};
+
+struct FileStatus
+{
+ u32 offset;
+ u32 size;
+};
+
+class FileSystem
+{
+public:
+ virtual ~FileSystem() = default;
+
+ virtual void DoState(PointerWrap& p) = 0;
+
+ /// Format the file system.
+ virtual ResultCode Format(Uid uid) = 0;
+
+ /// Get a file descriptor for accessing a file.
+ virtual Result OpenFile(Uid uid, Gid gid, const std::string& path, Mode mode) = 0;
+ /// Close a file descriptor.
+ virtual ResultCode Close(Fd fd) = 0;
+ /// Read `size` bytes from the file descriptor. Returns the number of bytes read.
+ virtual Result ReadBytesFromFile(Fd fd, u8* ptr, u32 size) = 0;
+ /// Write `size` bytes to the file descriptor. Returns the number of bytes written.
+ virtual Result WriteBytesToFile(Fd fd, const u8* ptr, u32 size) = 0;
+ /// Reposition the file offset for a file descriptor.
+ virtual Result SeekFile(Fd fd, u32 offset, SeekMode mode) = 0;
+ /// Get status for a file descriptor.
+ virtual Result GetFileStatus(Fd fd) = 0;
+
+ template
+ Result ReadFile(Fd fd, T* ptr, u32 count)
+ {
+ const Result bytes = ReadBytesFromFile(fd, reinterpret_cast(ptr), sizeof(T) * count);
+ if (!bytes)
+ return bytes.Error();
+ if (*bytes != sizeof(T) * count)
+ return ResultCode::ShortRead;
+ return count;
+ }
+
+ template
+ Result WriteFile(Fd fd, const T* ptr, u32 count)
+ {
+ const auto result = WriteBytesToFile(fd, reinterpret_cast(ptr), sizeof(T) * count);
+ if (!result)
+ return result.Error();
+ return count;
+ }
+
+ /// Create a file with the specified path and metadata.
+ virtual ResultCode CreateFile(Uid caller_uid, Gid caller_gid, const std::string& path,
+ FileAttribute attribute, Mode owner_mode, Mode group_mode,
+ Mode other_mode) = 0;
+ /// Create a directory with the specified path and metadata.
+ virtual ResultCode CreateDirectory(Uid caller_uid, Gid caller_gid, const std::string& path,
+ FileAttribute attribute, Mode owner_mode, Mode group_mode,
+ Mode other_mode) = 0;
+
+ /// Delete a file or directory with the specified path.
+ virtual ResultCode Delete(Uid caller_uid, Gid caller_gid, const std::string& path) = 0;
+ /// Rename a file or directory with the specified path.
+ virtual ResultCode Rename(Uid caller_uid, Gid caller_gid, const std::string& old_path,
+ const std::string& new_path) = 0;
+
+ /// List the children of a directory (non-recursively).
+ virtual Result> ReadDirectory(Uid caller_uid, Gid caller_gid,
+ const std::string& path) = 0;
+
+ /// Get metadata about a file.
+ virtual Result GetMetadata(Uid caller_uid, Gid caller_gid, const std::string& path) = 0;
+ /// Set metadata for a file.
+ virtual ResultCode SetMetadata(Uid caller_uid, const std::string& path, Uid uid, Gid gid,
+ FileAttribute attribute, Mode owner_mode, Mode group_mode,
+ Mode other_mode) = 0;
+
+ /// Get usage information about the NAND (block size, cluster and inode counts).
+ virtual Result GetNandStats() = 0;
+ /// Get usage information about a directory (used cluster and inode counts).
+ virtual Result GetDirectoryStats(const std::string& path) = 0;
+};
+
+} // namespace IOS::HLE::FS