diff options
| author | 2018-03-19 22:58:55 -0500 | |
|---|---|---|
| committer | 2018-03-19 22:58:55 -0500 | |
| commit | a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c (patch) | |
| tree | d31aeca8eacb374ab130dcd2449744cde2d5befd /src/core/file_sys | |
| parent | FS: Support the file Append open mode. (diff) | |
| download | yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar.gz yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar.xz yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.zip | |
FS: Updated the Directory Entry structure to match the Switch.
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/directory.h | 37 | ||||
| -rw-r--r-- | src/core/file_sys/disk_filesystem.cpp | 48 | ||||
| -rw-r--r-- | src/core/file_sys/disk_filesystem.h | 22 | ||||
| -rw-r--r-- | src/core/file_sys/filesystem.h | 2 | ||||
| -rw-r--r-- | src/core/file_sys/romfs_filesystem.h | 5 |
5 files changed, 84 insertions, 30 deletions
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h index 5a40bf472..c7639795e 100644 --- a/src/core/file_sys/directory.h +++ b/src/core/file_sys/directory.h | |||
| @@ -6,34 +6,28 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstddef> | 8 | #include <cstddef> |
| 9 | #include "common/common_funcs.h" | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/file_sys/filesystem.h" | ||
| 10 | 12 | ||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 12 | // FileSys namespace | 14 | // FileSys namespace |
| 13 | 15 | ||
| 14 | namespace FileSys { | 16 | namespace FileSys { |
| 15 | 17 | ||
| 16 | // Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format | 18 | // Structure of a directory entry, from |
| 17 | const size_t FILENAME_LENGTH = 0x20C / 2; | 19 | // http://switchbrew.org/index.php?title=Filesystem_services#DirectoryEntry |
| 20 | const size_t FILENAME_LENGTH = 0x300; | ||
| 18 | struct Entry { | 21 | struct Entry { |
| 19 | char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) | 22 | char filename[FILENAME_LENGTH]; |
| 20 | std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) | 23 | INSERT_PADDING_BYTES(4); |
| 21 | char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) | 24 | EntryType type; |
| 22 | std::array<char, 4> | 25 | INSERT_PADDING_BYTES(3); |
| 23 | extension; // 8.3 file extension (set to spaces for directories, null-terminated) | 26 | u64 file_size; |
| 24 | char unknown2; // unknown (always 0x01) | ||
| 25 | char unknown3; // unknown (0x00 or 0x08) | ||
| 26 | char is_directory; // directory flag | ||
| 27 | char is_hidden; // hidden flag | ||
| 28 | char is_archive; // archive flag | ||
| 29 | char is_read_only; // read-only flag | ||
| 30 | u64 file_size; // file size (for files only) | ||
| 31 | }; | 27 | }; |
| 32 | static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); | 28 | static_assert(sizeof(Entry) == 0x310, "Directory Entry struct isn't exactly 0x310 bytes long!"); |
| 33 | static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); | 29 | static_assert(offsetof(Entry, type) == 0x304, "Wrong offset for type in Entry."); |
| 34 | static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension in Entry."); | 30 | static_assert(offsetof(Entry, file_size) == 0x308, "Wrong offset for file_size in Entry."); |
| 35 | static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); | ||
| 36 | static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); | ||
| 37 | 31 | ||
| 38 | class DirectoryBackend : NonCopyable { | 32 | class DirectoryBackend : NonCopyable { |
| 39 | public: | 33 | public: |
| @@ -46,7 +40,10 @@ public: | |||
| 46 | * @param entries Buffer to read data into | 40 | * @param entries Buffer to read data into |
| 47 | * @return Number of entries listed | 41 | * @return Number of entries listed |
| 48 | */ | 42 | */ |
| 49 | virtual u32 Read(const u32 count, Entry* entries) = 0; | 43 | virtual u64 Read(const u64 count, Entry* entries) = 0; |
| 44 | |||
| 45 | /// Returns the number of entries still left to read. | ||
| 46 | virtual u64 GetEntryCount() const = 0; | ||
| 50 | 47 | ||
| 51 | /** | 48 | /** |
| 52 | * Close the directory | 49 | * Close the directory |
diff --git a/src/core/file_sys/disk_filesystem.cpp b/src/core/file_sys/disk_filesystem.cpp index 9d456e0bf..e2092b9df 100644 --- a/src/core/file_sys/disk_filesystem.cpp +++ b/src/core/file_sys/disk_filesystem.cpp | |||
| @@ -153,14 +153,50 @@ bool Disk_Storage::SetSize(const u64 size) const { | |||
| 153 | return false; | 153 | return false; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | u32 Disk_Directory::Read(const u32 count, Entry* entries) { | 156 | Disk_Directory::Disk_Directory(const std::string& path) : directory() { |
| 157 | LOG_WARNING(Service_FS, "(STUBBED) called"); | 157 | unsigned size = FileUtil::ScanDirectoryTree(path, directory); |
| 158 | return 0; | 158 | directory.size = size; |
| 159 | directory.isDirectory = true; | ||
| 160 | children_iterator = directory.children.begin(); | ||
| 161 | } | ||
| 162 | |||
| 163 | u64 Disk_Directory::Read(const u64 count, Entry* entries) { | ||
| 164 | u64 entries_read = 0; | ||
| 165 | |||
| 166 | while (entries_read < count && children_iterator != directory.children.cend()) { | ||
| 167 | const FileUtil::FSTEntry& file = *children_iterator; | ||
| 168 | const std::string& filename = file.virtualName; | ||
| 169 | Entry& entry = entries[entries_read]; | ||
| 170 | |||
| 171 | LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, | ||
| 172 | file.isDirectory); | ||
| 173 | |||
| 174 | // TODO(Link Mauve): use a proper conversion to UTF-16. | ||
| 175 | for (size_t j = 0; j < FILENAME_LENGTH; ++j) { | ||
| 176 | entry.filename[j] = filename[j]; | ||
| 177 | if (!filename[j]) | ||
| 178 | break; | ||
| 179 | } | ||
| 180 | |||
| 181 | if (file.isDirectory) { | ||
| 182 | entry.file_size = 0; | ||
| 183 | entry.type = EntryType::Directory; | ||
| 184 | } else { | ||
| 185 | entry.file_size = file.size; | ||
| 186 | entry.type = EntryType::File; | ||
| 187 | } | ||
| 188 | |||
| 189 | ++entries_read; | ||
| 190 | ++children_iterator; | ||
| 191 | } | ||
| 192 | return entries_read; | ||
| 159 | } | 193 | } |
| 160 | 194 | ||
| 161 | bool Disk_Directory::Close() const { | 195 | u64 Disk_Directory::GetEntryCount() const { |
| 162 | LOG_WARNING(Service_FS, "(STUBBED) called"); | 196 | // We convert the children iterator into a const_iterator to allow template argument deduction |
| 163 | return true; | 197 | // in std::distance. |
| 198 | std::vector<FileUtil::FSTEntry>::const_iterator current = children_iterator; | ||
| 199 | return std::distance(current, directory.children.end()); | ||
| 164 | } | 200 | } |
| 165 | 201 | ||
| 166 | } // namespace FileSys | 202 | } // namespace FileSys |
diff --git a/src/core/file_sys/disk_filesystem.h b/src/core/file_sys/disk_filesystem.h index 53767b949..29383dbf7 100644 --- a/src/core/file_sys/disk_filesystem.h +++ b/src/core/file_sys/disk_filesystem.h | |||
| @@ -59,8 +59,26 @@ private: | |||
| 59 | 59 | ||
| 60 | class Disk_Directory : public DirectoryBackend { | 60 | class Disk_Directory : public DirectoryBackend { |
| 61 | public: | 61 | public: |
| 62 | u32 Read(const u32 count, Entry* entries) override; | 62 | Disk_Directory(const std::string& path); |
| 63 | bool Close() const override; | 63 | |
| 64 | ~Disk_Directory() override { | ||
| 65 | Close(); | ||
| 66 | } | ||
| 67 | |||
| 68 | u64 Read(const u64 count, Entry* entries) override; | ||
| 69 | u64 GetEntryCount() const override; | ||
| 70 | |||
| 71 | bool Close() const override { | ||
| 72 | return true; | ||
| 73 | } | ||
| 74 | |||
| 75 | protected: | ||
| 76 | u32 total_entries_in_directory; | ||
| 77 | FileUtil::FSTEntry directory; | ||
| 78 | |||
| 79 | // We need to remember the last entry we returned, so a subsequent call to Read will continue | ||
| 80 | // from the next one. This iterator will always point to the next unread entry. | ||
| 81 | std::vector<FileUtil::FSTEntry>::iterator children_iterator; | ||
| 64 | }; | 82 | }; |
| 65 | 83 | ||
| 66 | } // namespace FileSys | 84 | } // namespace FileSys |
diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h index 4c9993efa..5c91a46c2 100644 --- a/src/core/file_sys/filesystem.h +++ b/src/core/file_sys/filesystem.h | |||
| @@ -27,7 +27,7 @@ enum LowPathType : u32 { | |||
| 27 | Wchar = 4, | 27 | Wchar = 4, |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | enum EntryType : u32 { | 30 | enum EntryType : u8 { |
| 31 | Directory = 0, | 31 | Directory = 0, |
| 32 | File = 1, | 32 | File = 1, |
| 33 | }; | 33 | }; |
diff --git a/src/core/file_sys/romfs_filesystem.h b/src/core/file_sys/romfs_filesystem.h index cedd70645..be52f20ef 100644 --- a/src/core/file_sys/romfs_filesystem.h +++ b/src/core/file_sys/romfs_filesystem.h | |||
| @@ -70,7 +70,10 @@ private: | |||
| 70 | 70 | ||
| 71 | class ROMFSDirectory : public DirectoryBackend { | 71 | class ROMFSDirectory : public DirectoryBackend { |
| 72 | public: | 72 | public: |
| 73 | u32 Read(const u32 count, Entry* entries) override { | 73 | u64 Read(const u64 count, Entry* entries) override { |
| 74 | return 0; | ||
| 75 | } | ||
| 76 | u64 GetEntryCount() const override { | ||
| 74 | return 0; | 77 | return 0; |
| 75 | } | 78 | } |
| 76 | bool Close() const override { | 79 | bool Close() const override { |