aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>2014-09-12 00:44:16 +0200
committerGravatar Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>2014-09-17 14:35:45 +0000
commite73caaefe58503f7d1d79a08e71bf66b5fe6edba (patch)
treefda0ffc5bc226d2cefc3dfa376f4ac78a7666bfb
parent9251f7e2f8dbb507f0846c680c6f2af155724e7a (diff)
Core: Add a passthrough backend for the filesystem, exposed as SDMC.
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/file_sys/archive_sdmc.cpp96
-rw-r--r--src/core/file_sys/archive_sdmc.h79
-rw-r--r--src/core/file_sys/file_sdmc.cpp63
-rw-r--r--src/core/file_sys/file_sdmc.h60
5 files changed, 302 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 14c114b6..46e11d77 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -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
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
new file mode 100644
index 00000000..fb155430
--- /dev/null
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -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
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
new file mode 100644
index 00000000..931817e5
--- /dev/null
+++ b/src/core/file_sys/archive_sdmc.h
@@ -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
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp
new file mode 100644
index 00000000..76adc640
--- /dev/null
+++ b/src/core/file_sys/file_sdmc.cpp
@@ -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
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h
new file mode 100644
index 00000000..b2e46f44
--- /dev/null
+++ b/src/core/file_sys/file_sdmc.h
@@ -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