diff options
| author | 2014-09-18 22:27:06 -0400 | |
|---|---|---|
| committer | 2014-09-18 22:27:06 -0400 | |
| commit | a9630a9d2b432bea7bdfef4aa462035b98b34517 (patch) | |
| tree | 258010943e989fc61a2a439ff15ead7ed3d11a6f /src/core/file_sys | |
| parent | Merge pull request #107 from lioncash/sprintf (diff) | |
| parent | Kernel: Implement the Close command for Archive, File and Directory. (diff) | |
| download | yuzu-a9630a9d2b432bea7bdfef4aa462035b98b34517.tar.gz yuzu-a9630a9d2b432bea7bdfef4aa462035b98b34517.tar.xz yuzu-a9630a9d2b432bea7bdfef4aa462035b98b34517.zip | |
Merge pull request #70 from linkmauve/master
Implement filesystem services, and the required kernel objects.
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/archive.h | 28 | ||||
| -rw-r--r-- | src/core/file_sys/archive_romfs.cpp | 21 | ||||
| -rw-r--r-- | src/core/file_sys/archive_romfs.h | 15 | ||||
| -rw-r--r-- | src/core/file_sys/archive_sdmc.cpp | 108 | ||||
| -rw-r--r-- | src/core/file_sys/archive_sdmc.h | 86 | ||||
| -rw-r--r-- | src/core/file_sys/directory.h | 53 | ||||
| -rw-r--r-- | src/core/file_sys/directory_romfs.cpp | 38 | ||||
| -rw-r--r-- | src/core/file_sys/directory_romfs.h | 37 | ||||
| -rw-r--r-- | src/core/file_sys/directory_sdmc.cpp | 86 | ||||
| -rw-r--r-- | src/core/file_sys/directory_sdmc.h | 45 | ||||
| -rw-r--r-- | src/core/file_sys/file.h | 53 | ||||
| -rw-r--r-- | src/core/file_sys/file_romfs.cpp | 59 | ||||
| -rw-r--r-- | src/core/file_sys/file_romfs.h | 54 | ||||
| -rw-r--r-- | src/core/file_sys/file_sdmc.cpp | 63 | ||||
| -rw-r--r-- | src/core/file_sys/file_sdmc.h | 60 |
15 files changed, 806 insertions, 0 deletions
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h index ac5630bea..560db6dea 100644 --- a/src/core/file_sys/archive.h +++ b/src/core/file_sys/archive.h | |||
| @@ -4,7 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/bit_field.h" | ||
| 11 | |||
| 12 | #include "core/file_sys/file.h" | ||
| 13 | #include "core/file_sys/directory.h" | ||
| 8 | 14 | ||
| 9 | #include "core/hle/kernel/kernel.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 10 | 16 | ||
| @@ -13,6 +19,13 @@ | |||
| 13 | 19 | ||
| 14 | namespace FileSys { | 20 | namespace FileSys { |
| 15 | 21 | ||
| 22 | union Mode { | ||
| 23 | u32 hex; | ||
| 24 | BitField<0, 1, u32> read_flag; | ||
| 25 | BitField<1, 1, u32> write_flag; | ||
| 26 | BitField<2, 1, u32> create_flag; | ||
| 27 | }; | ||
| 28 | |||
| 16 | class Archive : NonCopyable { | 29 | class Archive : NonCopyable { |
| 17 | public: | 30 | public: |
| 18 | /// Supported archive types | 31 | /// Supported archive types |
| @@ -36,6 +49,21 @@ public: | |||
| 36 | virtual IdCode GetIdCode() const = 0; | 49 | virtual IdCode GetIdCode() const = 0; |
| 37 | 50 | ||
| 38 | /** | 51 | /** |
| 52 | * Open a file specified by its path, using the specified mode | ||
| 53 | * @param path Path relative to the archive | ||
| 54 | * @param mode Mode to open the file with | ||
| 55 | * @return Opened file, or nullptr | ||
| 56 | */ | ||
| 57 | virtual std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const = 0; | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Open a directory specified by its path | ||
| 61 | * @param path Path relative to the archive | ||
| 62 | * @return Opened directory, or nullptr | ||
| 63 | */ | ||
| 64 | virtual std::unique_ptr<Directory> OpenDirectory(const std::string& path) const = 0; | ||
| 65 | |||
| 66 | /** | ||
| 39 | * Read data from the archive | 67 | * Read data from the archive |
| 40 | * @param offset Offset in bytes to start reading data from | 68 | * @param offset Offset in bytes to start reading data from |
| 41 | * @param length Length in bytes of data to read from archive | 69 | * @param length Length in bytes of data to read from archive |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index dc3fb1807..9bab3471f 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | 6 | ||
| 7 | #include "core/file_sys/archive_romfs.h" | 7 | #include "core/file_sys/archive_romfs.h" |
| 8 | #include "core/file_sys/directory_romfs.h" | ||
| 9 | #include "core/file_sys/file_romfs.h" | ||
| 8 | 10 | ||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 10 | // FileSys namespace | 12 | // FileSys namespace |
| @@ -22,6 +24,25 @@ Archive_RomFS::~Archive_RomFS() { | |||
| 22 | } | 24 | } |
| 23 | 25 | ||
| 24 | /** | 26 | /** |
| 27 | * Open a file specified by its path, using the specified mode | ||
| 28 | * @param path Path relative to the archive | ||
| 29 | * @param mode Mode to open the file with | ||
| 30 | * @return Opened file, or nullptr | ||
| 31 | */ | ||
| 32 | std::unique_ptr<File> Archive_RomFS::OpenFile(const std::string& path, const Mode mode) const { | ||
| 33 | return std::unique_ptr<File>(new File_RomFS); | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Open a directory specified by its path | ||
| 38 | * @param path Path relative to the archive | ||
| 39 | * @return Opened directory, or nullptr | ||
| 40 | */ | ||
| 41 | std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const std::string& path) const { | ||
| 42 | return std::unique_ptr<Directory>(new Directory_RomFS); | ||
| 43 | } | ||
| 44 | |||
| 45 | /** | ||
| 25 | * Read data from the archive | 46 | * Read data from the archive |
| 26 | * @param offset Offset in bytes to start reading data from | 47 | * @param offset Offset in bytes to start reading data from |
| 27 | * @param length Length in bytes of data to read from archive | 48 | * @param length Length in bytes of data to read from archive |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index e9ed6f77a..fcdefa95f 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -29,6 +29,21 @@ public: | |||
| 29 | IdCode GetIdCode() const override { return IdCode::RomFS; }; | 29 | IdCode GetIdCode() const override { return IdCode::RomFS; }; |
| 30 | 30 | ||
| 31 | /** | 31 | /** |
| 32 | * Open a file specified by its path, using the specified mode | ||
| 33 | * @param path Path relative to the archive | ||
| 34 | * @param mode Mode to open the file with | ||
| 35 | * @return Opened file, or nullptr | ||
| 36 | */ | ||
| 37 | std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * Open a directory specified by its path | ||
| 41 | * @param path Path relative to the archive | ||
| 42 | * @return Opened directory, or nullptr | ||
| 43 | */ | ||
| 44 | std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override; | ||
| 45 | |||
| 46 | /** | ||
| 32 | * Read data from the archive | 47 | * Read data from the archive |
| 33 | * @param offset Offset in bytes to start reading data from | 48 | * @param offset Offset in bytes to start reading data from |
| 34 | * @param length Length in bytes of data to read from archive | 49 | * @param length Length in bytes of data to read from archive |
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp new file mode 100644 index 000000000..30d33be5f --- /dev/null +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/archive_sdmc.h" | ||
| 11 | #include "core/file_sys/directory_sdmc.h" | ||
| 12 | #include "core/file_sys/file_sdmc.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | Archive_SDMC::Archive_SDMC(const std::string& mount_point) { | ||
| 20 | this->mount_point = mount_point; | ||
| 21 | DEBUG_LOG(FILESYS, "Directory %s set as SDMC.", mount_point.c_str()); | ||
| 22 | } | ||
| 23 | |||
| 24 | Archive_SDMC::~Archive_SDMC() { | ||
| 25 | } | ||
| 26 | |||
| 27 | bool Archive_SDMC::Initialize() { | ||
| 28 | if (!FileUtil::IsDirectory(mount_point)) { | ||
| 29 | WARN_LOG(FILESYS, "Directory %s not found, disabling SDMC.", mount_point.c_str()); | ||
| 30 | return false; | ||
| 31 | } | ||
| 32 | |||
| 33 | return true; | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Open a file specified by its path, using the specified mode | ||
| 38 | * @param path Path relative to the archive | ||
| 39 | * @param mode Mode to open the file with | ||
| 40 | * @return Opened file, or nullptr | ||
| 41 | */ | ||
| 42 | std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode mode) const { | ||
| 43 | DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.c_str(), mode); | ||
| 44 | File_SDMC* file = new File_SDMC(this, path, mode); | ||
| 45 | return std::unique_ptr<File>(file); | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Open a directory specified by its path | ||
| 50 | * @param path Path relative to the archive | ||
| 51 | * @return Opened directory, or nullptr | ||
| 52 | */ | ||
| 53 | std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const std::string& path) const { | ||
| 54 | DEBUG_LOG(FILESYS, "called path=%s", path.c_str()); | ||
| 55 | Directory_SDMC* directory = new Directory_SDMC(this, path); | ||
| 56 | return std::unique_ptr<Directory>(directory); | ||
| 57 | } | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Read data from the archive | ||
| 61 | * @param offset Offset in bytes to start reading archive from | ||
| 62 | * @param length Length in bytes to read data from archive | ||
| 63 | * @param buffer Buffer to read data into | ||
| 64 | * @return Number of bytes read | ||
| 65 | */ | ||
| 66 | size_t Archive_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 67 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 68 | return -1; | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Write data to the archive | ||
| 73 | * @param offset Offset in bytes to start writing data to | ||
| 74 | * @param length Length in bytes of data to write to archive | ||
| 75 | * @param buffer Buffer to write data from | ||
| 76 | * @param flush The flush parameters (0 == do not flush) | ||
| 77 | * @return Number of bytes written | ||
| 78 | */ | ||
| 79 | size_t Archive_SDMC::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { | ||
| 80 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 81 | return -1; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Get the size of the archive in bytes | ||
| 86 | * @return Size of the archive in bytes | ||
| 87 | */ | ||
| 88 | size_t Archive_SDMC::GetSize() const { | ||
| 89 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Set the size of the archive in bytes | ||
| 95 | */ | ||
| 96 | void Archive_SDMC::SetSize(const u64 size) { | ||
| 97 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 98 | } | ||
| 99 | |||
| 100 | /** | ||
| 101 | * Getter for the path used for this Archive | ||
| 102 | * @return Mount point of that passthrough archive | ||
| 103 | */ | ||
| 104 | std::string Archive_SDMC::GetMountPoint() const { | ||
| 105 | return mount_point; | ||
| 106 | } | ||
| 107 | |||
| 108 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h new file mode 100644 index 000000000..946f8b957 --- /dev/null +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/archive.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | /// File system interface to the SDMC archive | ||
| 18 | class Archive_SDMC final : public Archive { | ||
| 19 | public: | ||
| 20 | Archive_SDMC(const std::string& mount_point); | ||
| 21 | ~Archive_SDMC() override; | ||
| 22 | |||
| 23 | bool Initialize(); | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||
| 27 | * @return IdCode of the archive | ||
| 28 | */ | ||
| 29 | IdCode GetIdCode() const override { return IdCode::SDMC; }; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Open a file specified by its path, using the specified mode | ||
| 33 | * @param path Path relative to the archive | ||
| 34 | * @param mode Mode to open the file with | ||
| 35 | * @return Opened file, or nullptr | ||
| 36 | */ | ||
| 37 | std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * Open a directory specified by its path | ||
| 41 | * @param path Path relative to the archive | ||
| 42 | * @return Opened directory, or nullptr | ||
| 43 | */ | ||
| 44 | std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Read data from the archive | ||
| 48 | * @param offset Offset in bytes to start reading archive from | ||
| 49 | * @param length Length in bytes to read data from archive | ||
| 50 | * @param buffer Buffer to read data into | ||
| 51 | * @return Number of bytes read | ||
| 52 | */ | ||
| 53 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Write data to the archive | ||
| 57 | * @param offset Offset in bytes to start writing data to | ||
| 58 | * @param length Length in bytes of data to write to archive | ||
| 59 | * @param buffer Buffer to write data from | ||
| 60 | * @param flush The flush parameters (0 == do not flush) | ||
| 61 | * @return Number of bytes written | ||
| 62 | */ | ||
| 63 | size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; | ||
| 64 | |||
| 65 | /** | ||
| 66 | * Get the size of the archive in bytes | ||
| 67 | * @return Size of the archive in bytes | ||
| 68 | */ | ||
| 69 | size_t GetSize() const override; | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Set the size of the archive in bytes | ||
| 73 | */ | ||
| 74 | void SetSize(const u64 size) override; | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Getter for the path used for this Archive | ||
| 78 | * @return Mount point of that passthrough archive | ||
| 79 | */ | ||
| 80 | std::string GetMountPoint() const; | ||
| 81 | |||
| 82 | private: | ||
| 83 | std::string mount_point; | ||
| 84 | }; | ||
| 85 | |||
| 86 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h new file mode 100644 index 000000000..cf9a2010b --- /dev/null +++ b/src/core/file_sys/directory.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/hle/kernel/kernel.h" | ||
| 10 | |||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 12 | // FileSys namespace | ||
| 13 | |||
| 14 | namespace FileSys { | ||
| 15 | |||
| 16 | // Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format | ||
| 17 | const size_t FILENAME_LENGTH = 0x20C / 2; | ||
| 18 | struct Entry { | ||
| 19 | char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) | ||
| 20 | char short_name[8]; // 8.3 file name ('longfilename' -> 'LONGFI~1') | ||
| 21 | char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) | ||
| 22 | char extension[3]; // 8.3 file extension (set to spaces for directories) | ||
| 23 | char unknown2; // unknown (always 0x01) | ||
| 24 | char unknown3; // unknown (0x00 or 0x08) | ||
| 25 | char is_directory; // directory flag | ||
| 26 | char is_hidden; // hidden flag | ||
| 27 | char is_archive; // archive flag | ||
| 28 | char is_read_only; // read-only flag | ||
| 29 | u64 file_size; // file size (for files only) | ||
| 30 | }; | ||
| 31 | static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); | ||
| 32 | |||
| 33 | class Directory : NonCopyable { | ||
| 34 | public: | ||
| 35 | Directory() { } | ||
| 36 | virtual ~Directory() { } | ||
| 37 | |||
| 38 | /** | ||
| 39 | * List files contained in the directory | ||
| 40 | * @param count Number of entries to return at once in entries | ||
| 41 | * @param entries Buffer to read data into | ||
| 42 | * @return Number of entries listed | ||
| 43 | */ | ||
| 44 | virtual u32 Read(const u32 count, Entry* entries) = 0; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Close the directory | ||
| 48 | * @return true if the directory closed correctly | ||
| 49 | */ | ||
| 50 | virtual bool Close() const = 0; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_romfs.cpp b/src/core/file_sys/directory_romfs.cpp new file mode 100644 index 000000000..4e8f4c04d --- /dev/null +++ b/src/core/file_sys/directory_romfs.cpp | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | |||
| 7 | #include "core/file_sys/directory_romfs.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // FileSys namespace | ||
| 11 | |||
| 12 | namespace FileSys { | ||
| 13 | |||
| 14 | Directory_RomFS::Directory_RomFS() { | ||
| 15 | } | ||
| 16 | |||
| 17 | Directory_RomFS::~Directory_RomFS() { | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * List files contained in the directory | ||
| 22 | * @param count Number of entries to return at once in entries | ||
| 23 | * @param entries Buffer to read data into | ||
| 24 | * @return Number of entries listed | ||
| 25 | */ | ||
| 26 | u32 Directory_RomFS::Read(const u32 count, Entry* entries) { | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Close the directory | ||
| 32 | * @return true if the directory closed correctly | ||
| 33 | */ | ||
| 34 | bool Directory_RomFS::Close() const { | ||
| 35 | return false; | ||
| 36 | } | ||
| 37 | |||
| 38 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_romfs.h b/src/core/file_sys/directory_romfs.h new file mode 100644 index 000000000..4b71c4b13 --- /dev/null +++ b/src/core/file_sys/directory_romfs.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/directory.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | class Directory_RomFS final : public Directory { | ||
| 18 | public: | ||
| 19 | Directory_RomFS(); | ||
| 20 | ~Directory_RomFS() override; | ||
| 21 | |||
| 22 | /** | ||
| 23 | * List files contained in the directory | ||
| 24 | * @param count Number of entries to return at once in entries | ||
| 25 | * @param entries Buffer to read data into | ||
| 26 | * @return Number of entries listed | ||
| 27 | */ | ||
| 28 | u32 Read(const u32 count, Entry* entries) override; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Close the directory | ||
| 32 | * @return true if the directory closed correctly | ||
| 33 | */ | ||
| 34 | bool Close() const override; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp new file mode 100644 index 000000000..11e867857 --- /dev/null +++ b/src/core/file_sys/directory_sdmc.cpp | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/directory_sdmc.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const std::string& path) { | ||
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 20 | // the root directory we set while opening the archive. | ||
| 21 | // For example, opening /../../usr/bin can give the emulated program your installed programs. | ||
| 22 | std::string absolute_path = archive->GetMountPoint() + path; | ||
| 23 | entry_count = FileUtil::ScanDirectoryTree(absolute_path, entry); | ||
| 24 | current_entry = 0; | ||
| 25 | } | ||
| 26 | |||
| 27 | Directory_SDMC::~Directory_SDMC() { | ||
| 28 | Close(); | ||
| 29 | } | ||
| 30 | |||
| 31 | /** | ||
| 32 | * List files contained in the directory | ||
| 33 | * @param count Number of entries to return at once in entries | ||
| 34 | * @param entries Buffer to read data into | ||
| 35 | * @return Number of entries listed | ||
| 36 | */ | ||
| 37 | u32 Directory_SDMC::Read(const u32 count, Entry* entries) { | ||
| 38 | u32 i; | ||
| 39 | for (i = 0; i < count && current_entry < entry_count; ++i) { | ||
| 40 | FileUtil::FSTEntry file = entry.children[current_entry]; | ||
| 41 | std::string filename = file.virtualName; | ||
| 42 | WARN_LOG(FILESYS, "File %s: size=%d dir=%d", filename.c_str(), file.size, file.isDirectory); | ||
| 43 | |||
| 44 | Entry* entry = &entries[i]; | ||
| 45 | |||
| 46 | // TODO(Link Mauve): use a proper conversion to UTF-16. | ||
| 47 | for (int j = 0; j < FILENAME_LENGTH; ++j) { | ||
| 48 | entry->filename[j] = filename[j]; | ||
| 49 | if (!filename[j]) | ||
| 50 | break; | ||
| 51 | } | ||
| 52 | |||
| 53 | // Split the filename into 8.3 format. | ||
| 54 | // TODO(Link Mauve): move that to common, I guess, and make it more robust to long filenames. | ||
| 55 | std::string::size_type n = filename.rfind('.'); | ||
| 56 | if (n == std::string::npos) { | ||
| 57 | strncpy(entry->short_name, filename.c_str(), 8); | ||
| 58 | memset(entry->extension, '\0', 3); | ||
| 59 | } else { | ||
| 60 | strncpy(entry->short_name, filename.substr(0, n).c_str(), 8); | ||
| 61 | strncpy(entry->extension, filename.substr(n + 1).c_str(), 8); | ||
| 62 | } | ||
| 63 | |||
| 64 | entry->is_directory = file.isDirectory; | ||
| 65 | entry->file_size = file.size; | ||
| 66 | |||
| 67 | // We emulate a SD card where the archive bit has never been cleared, as it would be on | ||
| 68 | // most user SD cards. | ||
| 69 | // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a | ||
| 70 | // file bit. | ||
| 71 | entry->is_archive = !file.isDirectory; | ||
| 72 | |||
| 73 | ++current_entry; | ||
| 74 | } | ||
| 75 | return i; | ||
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Close the directory | ||
| 80 | * @return true if the directory closed correctly | ||
| 81 | */ | ||
| 82 | bool Directory_SDMC::Close() const { | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h new file mode 100644 index 000000000..0bc6c9eff --- /dev/null +++ b/src/core/file_sys/directory_sdmc.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/directory.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | #include "core/loader/loader.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | class Directory_SDMC final : public Directory { | ||
| 20 | public: | ||
| 21 | Directory_SDMC(); | ||
| 22 | Directory_SDMC(const Archive_SDMC* archive, const std::string& path); | ||
| 23 | ~Directory_SDMC() override; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * List files contained in the directory | ||
| 27 | * @param count Number of entries to return at once in entries | ||
| 28 | * @param entries Buffer to read data into | ||
| 29 | * @return Number of entries listed | ||
| 30 | */ | ||
| 31 | u32 Read(const u32 count, Entry* entries) override; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * Close the directory | ||
| 35 | * @return true if the directory closed correctly | ||
| 36 | */ | ||
| 37 | bool Close() const override; | ||
| 38 | |||
| 39 | private: | ||
| 40 | u32 entry_count; | ||
| 41 | u32 current_entry; | ||
| 42 | FileUtil::FSTEntry entry; | ||
| 43 | }; | ||
| 44 | |||
| 45 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file.h b/src/core/file_sys/file.h new file mode 100644 index 000000000..f7b009f5a --- /dev/null +++ b/src/core/file_sys/file.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/hle/kernel/kernel.h" | ||
| 10 | |||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 12 | // FileSys namespace | ||
| 13 | |||
| 14 | namespace FileSys { | ||
| 15 | |||
| 16 | class File : NonCopyable { | ||
| 17 | public: | ||
| 18 | File() { } | ||
| 19 | virtual ~File() { } | ||
| 20 | |||
| 21 | /** | ||
| 22 | * Read data from the file | ||
| 23 | * @param offset Offset in bytes to start reading data from | ||
| 24 | * @param length Length in bytes of data to read from file | ||
| 25 | * @param buffer Buffer to read data into | ||
| 26 | * @return Number of bytes read | ||
| 27 | */ | ||
| 28 | virtual size_t Read(const u64 offset, const u32 length, u8* buffer) const = 0; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Write data to the file | ||
| 32 | * @param offset Offset in bytes to start writing data to | ||
| 33 | * @param length Length in bytes of data to write to file | ||
| 34 | * @param buffer Buffer to write data from | ||
| 35 | * @param flush The flush parameters (0 == do not flush) | ||
| 36 | * @return Number of bytes written | ||
| 37 | */ | ||
| 38 | virtual size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const = 0; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Get the size of the file in bytes | ||
| 42 | * @return Size of the file in bytes | ||
| 43 | */ | ||
| 44 | virtual size_t GetSize() const = 0; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Close the file | ||
| 48 | * @return true if the file closed correctly | ||
| 49 | */ | ||
| 50 | virtual bool Close() const = 0; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_romfs.cpp b/src/core/file_sys/file_romfs.cpp new file mode 100644 index 000000000..00f3c2ea8 --- /dev/null +++ b/src/core/file_sys/file_romfs.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | |||
| 7 | #include "core/file_sys/file_romfs.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // FileSys namespace | ||
| 11 | |||
| 12 | namespace FileSys { | ||
| 13 | |||
| 14 | File_RomFS::File_RomFS() { | ||
| 15 | } | ||
| 16 | |||
| 17 | File_RomFS::~File_RomFS() { | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Read data from the file | ||
| 22 | * @param offset Offset in bytes to start reading data from | ||
| 23 | * @param length Length in bytes of data to read from file | ||
| 24 | * @param buffer Buffer to read data into | ||
| 25 | * @return Number of bytes read | ||
| 26 | */ | ||
| 27 | size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 28 | return -1; | ||
| 29 | } | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Write data to the file | ||
| 33 | * @param offset Offset in bytes to start writing data to | ||
| 34 | * @param length Length in bytes of data to write to file | ||
| 35 | * @param buffer Buffer to write data from | ||
| 36 | * @param flush The flush parameters (0 == do not flush) | ||
| 37 | * @return Number of bytes written | ||
| 38 | */ | ||
| 39 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||
| 40 | return -1; | ||
| 41 | } | ||
| 42 | |||
| 43 | /** | ||
| 44 | * Get the size of the file in bytes | ||
| 45 | * @return Size of the file in bytes | ||
| 46 | */ | ||
| 47 | size_t File_RomFS::GetSize() const { | ||
| 48 | return -1; | ||
| 49 | } | ||
| 50 | |||
| 51 | /** | ||
| 52 | * Close the file | ||
| 53 | * @return true if the file closed correctly | ||
| 54 | */ | ||
| 55 | bool File_RomFS::Close() const { | ||
| 56 | return false; | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_romfs.h b/src/core/file_sys/file_romfs.h new file mode 100644 index 000000000..5db43d4a0 --- /dev/null +++ b/src/core/file_sys/file_romfs.h | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/file.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | class File_RomFS final : public File { | ||
| 18 | public: | ||
| 19 | File_RomFS(); | ||
| 20 | ~File_RomFS() override; | ||
| 21 | |||
| 22 | /** | ||
| 23 | * Read data from the file | ||
| 24 | * @param offset Offset in bytes to start reading data from | ||
| 25 | * @param length Length in bytes of data to read from file | ||
| 26 | * @param buffer Buffer to read data into | ||
| 27 | * @return Number of bytes read | ||
| 28 | */ | ||
| 29 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Write data to the file | ||
| 33 | * @param offset Offset in bytes to start writing data to | ||
| 34 | * @param length Length in bytes of data to write to file | ||
| 35 | * @param buffer Buffer to write data from | ||
| 36 | * @param flush The flush parameters (0 == do not flush) | ||
| 37 | * @return Number of bytes written | ||
| 38 | */ | ||
| 39 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * Get the size of the file in bytes | ||
| 43 | * @return Size of the file in bytes | ||
| 44 | */ | ||
| 45 | size_t GetSize() const override; | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Close the file | ||
| 49 | * @return true if the file closed correctly | ||
| 50 | */ | ||
| 51 | bool Close() const override; | ||
| 52 | }; | ||
| 53 | |||
| 54 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp new file mode 100644 index 000000000..76adc6403 --- /dev/null +++ b/src/core/file_sys/file_sdmc.cpp | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/file_sdmc.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | File_SDMC::File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode) { | ||
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 20 | // the root directory we set while opening the archive. | ||
| 21 | // For example, opening /../../etc/passwd can give the emulated program your users list. | ||
| 22 | std::string real_path = archive->GetMountPoint() + path; | ||
| 23 | |||
| 24 | if (!mode.create_flag && !FileUtil::Exists(real_path)) { | ||
| 25 | file = nullptr; | ||
| 26 | return; | ||
| 27 | } | ||
| 28 | |||
| 29 | std::string mode_string; | ||
| 30 | if (mode.read_flag) | ||
| 31 | mode_string += "r"; | ||
| 32 | if (mode.write_flag) | ||
| 33 | mode_string += "w"; | ||
| 34 | |||
| 35 | file = new FileUtil::IOFile(real_path, mode_string.c_str()); | ||
| 36 | } | ||
| 37 | |||
| 38 | File_SDMC::~File_SDMC() { | ||
| 39 | Close(); | ||
| 40 | } | ||
| 41 | |||
| 42 | size_t File_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 43 | file->Seek(offset, SEEK_SET); | ||
| 44 | return file->ReadBytes(buffer, length); | ||
| 45 | } | ||
| 46 | |||
| 47 | size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||
| 48 | file->Seek(offset, SEEK_SET); | ||
| 49 | size_t written = file->WriteBytes(buffer, length); | ||
| 50 | if (flush) | ||
| 51 | file->Flush(); | ||
| 52 | return written; | ||
| 53 | } | ||
| 54 | |||
| 55 | size_t File_SDMC::GetSize() const { | ||
| 56 | return file->GetSize(); | ||
| 57 | } | ||
| 58 | |||
| 59 | bool File_SDMC::Close() const { | ||
| 60 | return file->Close(); | ||
| 61 | } | ||
| 62 | |||
| 63 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h new file mode 100644 index 000000000..b2e46f449 --- /dev/null +++ b/src/core/file_sys/file_sdmc.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/file.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | #include "core/loader/loader.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | class File_SDMC final : public File { | ||
| 20 | public: | ||
| 21 | File_SDMC(); | ||
| 22 | File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode); | ||
| 23 | ~File_SDMC() override; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Read data from the file | ||
| 27 | * @param offset Offset in bytes to start reading data from | ||
| 28 | * @param length Length in bytes of data to read from file | ||
| 29 | * @param buffer Buffer to read data into | ||
| 30 | * @return Number of bytes read | ||
| 31 | */ | ||
| 32 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * Write data to the file | ||
| 36 | * @param offset Offset in bytes to start writing data to | ||
| 37 | * @param length Length in bytes of data to write to file | ||
| 38 | * @param buffer Buffer to write data from | ||
| 39 | * @param flush The flush parameters (0 == do not flush) | ||
| 40 | * @return Number of bytes written | ||
| 41 | */ | ||
| 42 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||
| 43 | |||
| 44 | /** | ||
| 45 | * Get the size of the file in bytes | ||
| 46 | * @return Size of the file in bytes | ||
| 47 | */ | ||
| 48 | size_t GetSize() const override; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Close the file | ||
| 52 | * @return true if the file closed correctly | ||
| 53 | */ | ||
| 54 | bool Close() const override; | ||
| 55 | |||
| 56 | private: | ||
| 57 | FileUtil::IOFile* file; | ||
| 58 | }; | ||
| 59 | |||
| 60 | } // namespace FileSys | ||