summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2018-03-20 04:58:55 +0100
committerSubv <subv2112@gmail.com>2018-03-20 04:58:55 +0100
commita9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c (patch)
treed31aeca8eacb374ab130dcd2449744cde2d5befd
parentFS: Support the file Append open mode. (diff)
downloadyuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar
yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar.gz
yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar.bz2
yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar.lz
yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar.xz
yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.tar.zst
yuzu-a9ba2c2000d9f2e4c6018aa6fc1e754eca82f72c.zip
-rw-r--r--src/core/file_sys/directory.h37
-rw-r--r--src/core/file_sys/disk_filesystem.cpp48
-rw-r--r--src/core/file_sys/disk_filesystem.h22
-rw-r--r--src/core/file_sys/filesystem.h2
-rw-r--r--src/core/file_sys/romfs_filesystem.h5
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 @@
#include <array>
#include <cstddef>
+#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "core/file_sys/filesystem.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// FileSys namespace
namespace FileSys {
-// Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format
-const size_t FILENAME_LENGTH = 0x20C / 2;
+// Structure of a directory entry, from
+// http://switchbrew.org/index.php?title=Filesystem_services#DirectoryEntry
+const size_t FILENAME_LENGTH = 0x300;
struct Entry {
- char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated)
- std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated)
- char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD)
- std::array<char, 4>
- extension; // 8.3 file extension (set to spaces for directories, null-terminated)
- char unknown2; // unknown (always 0x01)
- char unknown3; // unknown (0x00 or 0x08)
- char is_directory; // directory flag
- char is_hidden; // hidden flag
- char is_archive; // archive flag
- char is_read_only; // read-only flag
- u64 file_size; // file size (for files only)
+ char filename[FILENAME_LENGTH];
+ INSERT_PADDING_BYTES(4);
+ EntryType type;
+ INSERT_PADDING_BYTES(3);
+ u64 file_size;
};
-static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!");
-static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry.");
-static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension in Entry.");
-static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry.");
-static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry.");
+static_assert(sizeof(Entry) == 0x310, "Directory Entry struct isn't exactly 0x310 bytes long!");
+static_assert(offsetof(Entry, type) == 0x304, "Wrong offset for type in Entry.");
+static_assert(offsetof(Entry, file_size) == 0x308, "Wrong offset for file_size in Entry.");
class DirectoryBackend : NonCopyable {
public:
@@ -46,7 +40,10 @@ public:
* @param entries Buffer to read data into
* @return Number of entries listed
*/
- virtual u32 Read(const u32 count, Entry* entries) = 0;
+ virtual u64 Read(const u64 count, Entry* entries) = 0;
+
+ /// Returns the number of entries still left to read.
+ virtual u64 GetEntryCount() const = 0;
/**
* 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 {
return false;
}
-u32 Disk_Directory::Read(const u32 count, Entry* entries) {
- LOG_WARNING(Service_FS, "(STUBBED) called");
- return 0;
+Disk_Directory::Disk_Directory(const std::string& path) : directory() {
+ unsigned size = FileUtil::ScanDirectoryTree(path, directory);
+ directory.size = size;
+ directory.isDirectory = true;
+ children_iterator = directory.children.begin();
+}
+
+u64 Disk_Directory::Read(const u64 count, Entry* entries) {
+ u64 entries_read = 0;
+
+ while (entries_read < count && children_iterator != directory.children.cend()) {
+ const FileUtil::FSTEntry& file = *children_iterator;
+ const std::string& filename = file.virtualName;
+ Entry& entry = entries[entries_read];
+
+ LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size,
+ file.isDirectory);
+
+ // TODO(Link Mauve): use a proper conversion to UTF-16.
+ for (size_t j = 0; j < FILENAME_LENGTH; ++j) {
+ entry.filename[j] = filename[j];
+ if (!filename[j])
+ break;
+ }
+
+ if (file.isDirectory) {
+ entry.file_size = 0;
+ entry.type = EntryType::Directory;
+ } else {
+ entry.file_size = file.size;
+ entry.type = EntryType::File;
+ }
+
+ ++entries_read;
+ ++children_iterator;
+ }
+ return entries_read;
}
-bool Disk_Directory::Close() const {
- LOG_WARNING(Service_FS, "(STUBBED) called");
- return true;
+u64 Disk_Directory::GetEntryCount() const {
+ // We convert the children iterator into a const_iterator to allow template argument deduction
+ // in std::distance.
+ std::vector<FileUtil::FSTEntry>::const_iterator current = children_iterator;
+ return std::distance(current, directory.children.end());
}
} // 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:
class Disk_Directory : public DirectoryBackend {
public:
- u32 Read(const u32 count, Entry* entries) override;
- bool Close() const override;
+ Disk_Directory(const std::string& path);
+
+ ~Disk_Directory() override {
+ Close();
+ }
+
+ u64 Read(const u64 count, Entry* entries) override;
+ u64 GetEntryCount() const override;
+
+ bool Close() const override {
+ return true;
+ }
+
+protected:
+ u32 total_entries_in_directory;
+ FileUtil::FSTEntry directory;
+
+ // We need to remember the last entry we returned, so a subsequent call to Read will continue
+ // from the next one. This iterator will always point to the next unread entry.
+ std::vector<FileUtil::FSTEntry>::iterator children_iterator;
};
} // 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 {
Wchar = 4,
};
-enum EntryType : u32 {
+enum EntryType : u8 {
Directory = 0,
File = 1,
};
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:
class ROMFSDirectory : public DirectoryBackend {
public:
- u32 Read(const u32 count, Entry* entries) override {
+ u64 Read(const u64 count, Entry* entries) override {
+ return 0;
+ }
+ u64 GetEntryCount() const override {
return 0;
}
bool Close() const override {