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/thumbemu.cpp | ||||
|             file_sys/archive_romfs.cpp | ||||
|             file_sys/archive_sdmc.cpp | ||||
|             file_sys/file_romfs.cpp | ||||
|             file_sys/file_sdmc.cpp | ||||
|             hle/kernel/address_arbiter.cpp | ||||
|             hle/kernel/archive.cpp | ||||
|             hle/kernel/event.cpp | ||||
| @@ -78,8 +80,10 @@ set(HEADERS | ||||
|             arm/arm_interface.h | ||||
|             file_sys/archive.h | ||||
|             file_sys/archive_romfs.h | ||||
|             file_sys/archive_sdmc.h | ||||
|             file_sys/file.h | ||||
|             file_sys/file_romfs.h | ||||
|             file_sys/file_sdmc.h | ||||
|             hle/kernel/address_arbiter.h | ||||
|             hle/kernel/archive.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