From 21bac2d7d757df18f184a8d79393ab8f91c0fc03 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 19 Mar 2018 23:01:47 -0500
Subject: [PATCH] FS: Added the IDirectory IPC interface and implemented its
 two functions.

---
 src/core/hle/service/filesystem/fsp_srv.cpp | 51 +++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 720ac9930..5536991bc 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -5,6 +5,7 @@
 #include <cinttypes>
 #include "common/logging/log.h"
 #include "core/core.h"
+#include "core/file_sys/directory.h"
 #include "core/file_sys/filesystem.h"
 #include "core/file_sys/storage.h"
 #include "core/hle/ipc_helpers.h"
@@ -151,6 +152,56 @@ private:
     }
 };
 
+class IDirectory final : public ServiceFramework<IDirectory> {
+public:
+    explicit IDirectory(std::unique_ptr<FileSys::DirectoryBackend>&& backend)
+        : ServiceFramework("IDirectory"), backend(std::move(backend)) {
+        static const FunctionInfo functions[] = {
+            {0, &IDirectory::Read, "Read"},
+            {1, &IDirectory::GetEntryCount, "GetEntryCount"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    std::unique_ptr<FileSys::DirectoryBackend> backend;
+
+    void Read(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        const u64 unk = rp.Pop<u64>();
+
+        LOG_DEBUG(Service_FS, "called, unk=0x%llx", unk);
+
+        // Calculate how many entries we can fit in the output buffer
+        u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry);
+
+        // Read the data from the Directory backend
+        std::vector<FileSys::Entry> entries(count_entries);
+        u64 read_entries = backend->Read(count_entries, entries.data());
+
+        // Convert the data into a byte array
+        std::vector<u8> output(entries.size() * sizeof(FileSys::Entry));
+        std::memcpy(output.data(), entries.data(), output.size());
+
+        // Write the data to memory
+        ctx.WriteBuffer(output);
+
+        IPC::ResponseBuilder rb{ctx, 4};
+        rb.Push(RESULT_SUCCESS);
+        rb.Push(read_entries);
+    }
+
+    void GetEntryCount(Kernel::HLERequestContext& ctx) {
+        LOG_DEBUG(Service_FS, "called");
+
+        u64 count = backend->GetEntryCount();
+
+        IPC::ResponseBuilder rb{ctx, 4};
+        rb.Push(RESULT_SUCCESS);
+        rb.Push(count);
+    }
+};
+
 class IFileSystem final : public ServiceFramework<IFileSystem> {
 public:
     explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend)