Core: Add a passthrough backend for the filesystem, exposed as SDMC.
This commit is contained in:
		| @@ -23,7 +23,9 @@ set(SRCS | |||||||
|             arm/interpreter/armvirt.cpp |             arm/interpreter/armvirt.cpp | ||||||
|             arm/interpreter/thumbemu.cpp |             arm/interpreter/thumbemu.cpp | ||||||
|             file_sys/archive_romfs.cpp |             file_sys/archive_romfs.cpp | ||||||
|  |             file_sys/archive_sdmc.cpp | ||||||
|             file_sys/file_romfs.cpp |             file_sys/file_romfs.cpp | ||||||
|  |             file_sys/file_sdmc.cpp | ||||||
|             hle/kernel/address_arbiter.cpp |             hle/kernel/address_arbiter.cpp | ||||||
|             hle/kernel/archive.cpp |             hle/kernel/archive.cpp | ||||||
|             hle/kernel/event.cpp |             hle/kernel/event.cpp | ||||||
| @@ -78,8 +80,10 @@ set(HEADERS | |||||||
|             arm/arm_interface.h |             arm/arm_interface.h | ||||||
|             file_sys/archive.h |             file_sys/archive.h | ||||||
|             file_sys/archive_romfs.h |             file_sys/archive_romfs.h | ||||||
|  |             file_sys/archive_sdmc.h | ||||||
|             file_sys/file.h |             file_sys/file.h | ||||||
|             file_sys/file_romfs.h |             file_sys/file_romfs.h | ||||||
|  |             file_sys/file_sdmc.h | ||||||
|             hle/kernel/address_arbiter.h |             hle/kernel/address_arbiter.h | ||||||
|             hle/kernel/archive.h |             hle/kernel/archive.h | ||||||
|             hle/kernel/event.h |             hle/kernel/event.h | ||||||
|   | |||||||
							
								
								
									
										96
									
								
								src/core/file_sys/archive_sdmc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/core/file_sys/archive_sdmc.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <sys/stat.h> | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/file_util.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/archive_sdmc.h" | ||||||
|  | #include "core/file_sys/file_sdmc.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | Archive_SDMC::Archive_SDMC(const std::string& mount_point) { | ||||||
|  |     this->mount_point = mount_point; | ||||||
|  |     DEBUG_LOG(FILESYS, "Directory %s set as SDMC.", mount_point.c_str()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Archive_SDMC::~Archive_SDMC() { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool Archive_SDMC::Initialize() { | ||||||
|  |     if (!FileUtil::IsDirectory(mount_point)) { | ||||||
|  |         WARN_LOG(FILESYS, "Directory %s not found, disabling SDMC.", mount_point.c_str()); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Open a file specified by its path, using the specified mode | ||||||
|  |  * @param path Path relative to the archive | ||||||
|  |  * @param mode Mode to open the file with | ||||||
|  |  * @return Opened file, or nullptr | ||||||
|  |  */ | ||||||
|  | std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode mode) const { | ||||||
|  |     DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.c_str(), mode); | ||||||
|  |     File_SDMC* file = new File_SDMC(this, path, mode); | ||||||
|  |     return std::unique_ptr<File>(file); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Read data from the archive | ||||||
|  |  * @param offset Offset in bytes to start reading archive from | ||||||
|  |  * @param length Length in bytes to read data from archive | ||||||
|  |  * @param buffer Buffer to read data into | ||||||
|  |  * @return Number of bytes read | ||||||
|  |  */ | ||||||
|  | size_t Archive_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||||||
|  |     ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Write data to the archive | ||||||
|  |  * @param offset Offset in bytes to start writing data to | ||||||
|  |  * @param length Length in bytes of data to write to archive | ||||||
|  |  * @param buffer Buffer to write data from | ||||||
|  |  * @param flush  The flush parameters (0 == do not flush) | ||||||
|  |  * @return Number of bytes written | ||||||
|  |  */ | ||||||
|  | size_t Archive_SDMC::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { | ||||||
|  |     ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get the size of the archive in bytes | ||||||
|  |  * @return Size of the archive in bytes | ||||||
|  |  */ | ||||||
|  | size_t Archive_SDMC::GetSize() const { | ||||||
|  |     ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Set the size of the archive in bytes | ||||||
|  |  */ | ||||||
|  | void Archive_SDMC::SetSize(const u64 size) { | ||||||
|  |     ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Getter for the path used for this Archive | ||||||
|  |  * @return Mount point of that passthrough archive | ||||||
|  |  */ | ||||||
|  | std::string Archive_SDMC::GetMountPoint() const { | ||||||
|  |     return mount_point; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
							
								
								
									
										79
									
								
								src/core/file_sys/archive_sdmc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/core/file_sys/archive_sdmc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/archive.h" | ||||||
|  | #include "core/loader/loader.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | /// File system interface to the SDMC archive | ||||||
|  | class Archive_SDMC final : public Archive { | ||||||
|  | public: | ||||||
|  |     Archive_SDMC(const std::string& mount_point); | ||||||
|  |     ~Archive_SDMC() override; | ||||||
|  |  | ||||||
|  |     bool Initialize(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||||||
|  |      * @return IdCode of the archive | ||||||
|  |      */ | ||||||
|  |     IdCode GetIdCode() const override { return IdCode::SDMC; }; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Open a file specified by its path, using the specified mode | ||||||
|  |      * @param path Path relative to the archive | ||||||
|  |      * @param mode Mode to open the file with | ||||||
|  |      * @return Opened file, or nullptr | ||||||
|  |      */ | ||||||
|  |     std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Read data from the archive | ||||||
|  |      * @param offset Offset in bytes to start reading archive from | ||||||
|  |      * @param length Length in bytes to read data from archive | ||||||
|  |      * @param buffer Buffer to read data into | ||||||
|  |      * @return Number of bytes read | ||||||
|  |      */ | ||||||
|  |     size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Write data to the archive | ||||||
|  |      * @param offset Offset in bytes to start writing data to | ||||||
|  |      * @param length Length in bytes of data to write to archive | ||||||
|  |      * @param buffer Buffer to write data from | ||||||
|  |      * @param flush  The flush parameters (0 == do not flush) | ||||||
|  |      * @return Number of bytes written | ||||||
|  |      */ | ||||||
|  |     size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Get the size of the archive in bytes | ||||||
|  |      * @return Size of the archive in bytes | ||||||
|  |      */ | ||||||
|  |     size_t GetSize() const override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Set the size of the archive in bytes | ||||||
|  |      */ | ||||||
|  |     void SetSize(const u64 size) override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Getter for the path used for this Archive | ||||||
|  |      * @return Mount point of that passthrough archive | ||||||
|  |      */ | ||||||
|  |     std::string GetMountPoint() const; | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     std::string mount_point; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
							
								
								
									
										63
									
								
								src/core/file_sys/file_sdmc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/core/file_sys/file_sdmc.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <sys/stat.h> | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/file_util.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/file_sdmc.h" | ||||||
|  | #include "core/file_sys/archive_sdmc.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | File_SDMC::File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode) { | ||||||
|  |     // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||||||
|  |     // the root directory we set while opening the archive. | ||||||
|  |     // For example, opening /../../etc/passwd can give the emulated program your users list. | ||||||
|  |     std::string real_path = archive->GetMountPoint() + path; | ||||||
|  |  | ||||||
|  |     if (!mode.create_flag && !FileUtil::Exists(real_path)) { | ||||||
|  |         file = nullptr; | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::string mode_string; | ||||||
|  |     if (mode.read_flag) | ||||||
|  |         mode_string += "r"; | ||||||
|  |     if (mode.write_flag) | ||||||
|  |         mode_string += "w"; | ||||||
|  |  | ||||||
|  |     file = new FileUtil::IOFile(real_path, mode_string.c_str()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | File_SDMC::~File_SDMC() { | ||||||
|  |     Close(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t File_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||||||
|  |     file->Seek(offset, SEEK_SET); | ||||||
|  |     return file->ReadBytes(buffer, length); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||||||
|  |     file->Seek(offset, SEEK_SET); | ||||||
|  |     size_t written = file->WriteBytes(buffer, length); | ||||||
|  |     if (flush) | ||||||
|  |         file->Flush(); | ||||||
|  |     return written; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t File_SDMC::GetSize() const { | ||||||
|  |     return file->GetSize(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool File_SDMC::Close() const { | ||||||
|  |     return file->Close(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
							
								
								
									
										60
									
								
								src/core/file_sys/file_sdmc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/core/file_sys/file_sdmc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/file_util.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/file.h" | ||||||
|  | #include "core/file_sys/archive_sdmc.h" | ||||||
|  | #include "core/loader/loader.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | class File_SDMC final : public File { | ||||||
|  | public: | ||||||
|  |     File_SDMC(); | ||||||
|  |     File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode); | ||||||
|  |     ~File_SDMC() override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Read data from the file | ||||||
|  |      * @param offset Offset in bytes to start reading data from | ||||||
|  |      * @param length Length in bytes of data to read from file | ||||||
|  |      * @param buffer Buffer to read data into | ||||||
|  |      * @return Number of bytes read | ||||||
|  |      */ | ||||||
|  |     size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Write data to the file | ||||||
|  |      * @param offset Offset in bytes to start writing data to | ||||||
|  |      * @param length Length in bytes of data to write to file | ||||||
|  |      * @param buffer Buffer to write data from | ||||||
|  |      * @param flush The flush parameters (0 == do not flush) | ||||||
|  |      * @return Number of bytes written | ||||||
|  |      */ | ||||||
|  |     size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Get the size of the file in bytes | ||||||
|  |      * @return Size of the file in bytes | ||||||
|  |      */ | ||||||
|  |     size_t GetSize() const override; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Close the file | ||||||
|  |      * @return true if the file closed correctly | ||||||
|  |      */ | ||||||
|  |     bool Close() const override; | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     FileUtil::IOFile* file; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
		Reference in New Issue
	
	Block a user