From afcaf200201a5c4653e208660f2add0bd66e6b5a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 22 Mar 2019 10:20:36 -0700 Subject: [PATCH] fs.mitm: ProxyFile, ProxyDirectory, ProxyFileSystem --- .../ams_mitm/source/fs_mitm/fs_idirectory.hpp | 41 ++++++- .../ams_mitm/source/fs_mitm/fs_ifile.hpp | 73 ++++++++++-- .../source/fs_mitm/fs_ifilesystem.hpp | 106 ++++++++++++++++++ 3 files changed, 207 insertions(+), 13 deletions(-) diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_idirectory.hpp b/stratosphere/ams_mitm/source/fs_mitm/fs_idirectory.hpp index 020b67dde..c141fa3d1 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_idirectory.hpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_idirectory.hpp @@ -28,7 +28,7 @@ enum FsIDirectoryCmd : u32 { class IDirectory { public: virtual ~IDirectory() {} - + Result Read(uint64_t *out_count, FsDirectoryEntry *out_entries, uint64_t max_entries) { if (out_count == nullptr) { return ResultFsNullptrArgument; @@ -42,14 +42,14 @@ class IDirectory { } return ReadImpl(out_count, out_entries, max_entries); } - + Result GetEntryCount(uint64_t *count) { if (count == nullptr) { return ResultFsNullptrArgument; } return GetEntryCountImpl(count); } - + protected: /* ...? */ private: @@ -83,3 +83,38 @@ class IDirectoryInterface : public IServiceObject { MakeServiceCommandMeta(), }; }; + +class ProxyDirectory : public IDirectory { + private: + std::unique_ptr base_dir; + public: + ProxyDirectory(FsDir *d) : base_dir(d) { + /* ... */ + } + + ProxyDirectory(std::unique_ptr d) : base_dir(std::move(d)) { + /* ... */ + } + + ProxyDirectory(FsDir d) { + this->base_dir = std::make_unique(d); + } + + virtual ~ProxyDirectory() { + fsDirClose(this->base_dir.get()); + } + public: + virtual Result ReadImpl(uint64_t *out_count, FsDirectoryEntry *out_entries, uint64_t max_entries) { + size_t count; + + Result rc = fsDirRead(this->base_dir.get(), 0, &count, max_entries, out_entries); + if (R_SUCCEEDED(rc)) { + *out_count = count; + } + + return rc; + } + virtual Result GetEntryCountImpl(uint64_t *count) { + return fsDirGetEntryCount(this->base_dir.get(), count); + } +}; diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_ifile.hpp b/stratosphere/ams_mitm/source/fs_mitm/fs_ifile.hpp index 85caa017e..be5de142f 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_ifile.hpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_ifile.hpp @@ -19,6 +19,7 @@ #include #include "fs_results.hpp" +#include "fs_shim.h" enum FsIFileCmd : u32 { FsIFileCmd_Read = 0, @@ -28,11 +29,11 @@ enum FsIFileCmd : u32 { FsIFileCmd_GetSize = 4, FsIFileCmd_OperateRange = 5, }; - + class IFile { public: virtual ~IFile() {} - + Result Read(uint64_t *out, uint64_t offset, void *buffer, uint64_t size, uint32_t flags) { (void)(flags); if (out == nullptr) { @@ -47,18 +48,18 @@ class IFile { } return ReadImpl(out, offset, buffer, size); } - + Result GetSize(uint64_t *out) { if (out == nullptr) { return ResultFsNullptrArgument; } return GetSizeImpl(out); } - + Result Flush() { return FlushImpl(); } - + Result Write(uint64_t offset, void *buffer, uint64_t size, uint32_t flags) { if (size == 0) { return 0; @@ -69,22 +70,22 @@ class IFile { const bool flush = (flags & 1) != 0; return WriteImpl(offset, buffer, size, flush); } - + Result Write(uint64_t offset, void *buffer, uint64_t size) { return Write(offset, buffer, size, false); } - + Result SetSize(uint64_t size) { return SetSizeImpl(size); } - + Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) { if (operation_type == 3) { return OperateRangeImpl(operation_type, offset, size, out_range_info); } return ResultFsUnsupportedOperation; } - + protected: /* ...? */ private: @@ -135,8 +136,60 @@ class IFileInterface : public IServiceObject { MakeServiceCommandMeta(), MakeServiceCommandMeta(), MakeServiceCommandMeta(), - + /* 4.0.0- */ MakeServiceCommandMeta(), }; }; + +class ProxyFile : public IFile { + private: + std::unique_ptr base_file; + public: + ProxyFile(FsFile *f) : base_file(f) { + /* ... */ + } + + ProxyFile(std::unique_ptr f) : base_file(std::move(f)) { + /* ... */ + } + + ProxyFile(FsFile f) { + this->base_file = std::make_unique(f); + } + + virtual ~ProxyFile() { + fsFileClose(this->base_file.get()); + } + public: + virtual Result ReadImpl(u64 *out, u64 offset, void *buffer, u64 size) { + size_t out_sz; + + Result rc = fsFileRead(this->base_file.get(), offset, buffer, size, &out_sz); + if (R_SUCCEEDED(rc)) { + *out = out_sz; + } + + return rc; + } + virtual Result GetSizeImpl(u64 *out) { + return fsFileGetSize(this->base_file.get(), out); + } + virtual Result FlushImpl() { + return fsFileFlush(this->base_file.get()); + } + virtual Result WriteImpl(u64 offset, void *buffer, u64 size, bool flush) { + Result rc = fsFileWrite(this->base_file.get(), offset, buffer, size); + if (R_SUCCEEDED(rc)) { + /* libnx doesn't allow passing the flush flag. */ + rc = fsFileFlush(this->base_file.get()); + } + return rc; + } + virtual Result SetSizeImpl(u64 size) { + return fsFileSetSize(this->base_file.get(), size); + } + virtual Result OperateRangeImpl(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) { + return fsFileOperateRange(this->base_file.get(), operation_type, offset, size, out_range_info); + } +}; diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_ifilesystem.hpp b/stratosphere/ams_mitm/source/fs_mitm/fs_ifilesystem.hpp index 8c5ebebb7..6e8d1211f 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_ifilesystem.hpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_ifilesystem.hpp @@ -429,3 +429,109 @@ class IFileSystemInterface : public IServiceObject { MakeServiceCommandMeta(), }; }; + +class ProxyFileSystem : public IFileSystem { + private: + std::unique_ptr base_fs; + public: + ProxyFileSystem(FsFileSystem *fs) : base_fs(fs) { + /* ... */ + } + + ProxyFileSystem(std::unique_ptr fs) : base_fs(std::move(fs)) { + /* ... */ + } + + ProxyFileSystem(FsFileSystem fs) { + this->base_fs = std::make_unique(fs); + } + + virtual ~ProxyFileSystem() { + fsFsClose(this->base_fs.get()); + } + + public: + virtual Result CreateFileImpl(FsPath &path, uint64_t size, int flags) { + return fsFsCreateFile(this->base_fs.get(), path.str, size, flags); + } + + virtual Result DeleteFileImpl(FsPath &path) { + return fsFsDeleteFile(this->base_fs.get(), path.str); + } + + virtual Result CreateDirectoryImpl(FsPath &path) { + return fsFsCreateDirectory(this->base_fs.get(), path.str); + } + + virtual Result DeleteDirectoryImpl(FsPath &path) { + return fsFsDeleteDirectory(this->base_fs.get(), path.str); + } + + virtual Result DeleteDirectoryRecursivelyImpl(FsPath &path) { + return fsFsDeleteDirectoryRecursively(this->base_fs.get(), path.str); + } + + virtual Result RenameFileImpl(FsPath &old_path, FsPath &new_path) { + return fsFsRenameFile(this->base_fs.get(), old_path.str, new_path.str); + } + + virtual Result RenameDirectoryImpl(FsPath &old_path, FsPath &new_path) { + return fsFsRenameDirectory(this->base_fs.get(), old_path.str, new_path.str); + } + + virtual Result GetEntryTypeImpl(DirectoryEntryType *out, FsPath &path) { + FsEntryType type; + + Result rc = fsFsGetEntryType(this->base_fs.get(), path.str, &type); + if (R_SUCCEEDED(rc)) { + *out = static_cast(static_cast(type)); + } + + return rc; + } + virtual Result OpenFileImpl(std::unique_ptr &out_file, FsPath &path, OpenMode mode) { + FsFile f; + + Result rc = fsFsOpenFile(this->base_fs.get(), path.str, static_cast(mode), &f); + if (R_SUCCEEDED(rc)) { + out_file = std::make_unique(f); + } + + return rc; + } + + virtual Result OpenDirectoryImpl(std::unique_ptr &out_dir, FsPath &path, DirectoryOpenMode mode) { + FsDir d; + + Result rc = fsFsOpenDirectory(this->base_fs.get(), path.str, static_cast(mode), &d); + if (R_SUCCEEDED(rc)) { + out_dir = std::make_unique(d); + } + + return rc; + } + + virtual Result CommitImpl() { + return fsFsCommit(this->base_fs.get()); + } + + virtual Result GetFreeSpaceSizeImpl(uint64_t *out, FsPath &path) { + return fsFsGetFreeSpace(this->base_fs.get(), path.str, out); + } + + virtual Result GetTotalSpaceSizeImpl(uint64_t *out, FsPath &path) { + return fsFsGetTotalSpace(this->base_fs.get(), path.str, out); + } + + virtual Result CleanDirectoryRecursivelyImpl(FsPath &path) { + return fsFsCleanDirectoryRecursively(this->base_fs.get(), path.str); + } + + virtual Result GetFileTimeStampRawImpl(FsTimeStampRaw *out, FsPath &path) { + return fsFsGetFileTimeStampRaw(this->base_fs.get(), path.str, out); + } + + virtual Result QueryEntryImpl(char *out, uint64_t out_size, const char *in, uint64_t in_size, int query, FsPath &path) { + return fsFsQueryEntry(this->base_fs.get(), out, out_size, in, in_size, path.str,static_cast(query)); + } +}; \ No newline at end of file