diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj
index a518b531f1..5b64898b7b 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -138,6 +138,7 @@
+
diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters
index 50ea0f619d..58b75ff30f 100644
--- a/Source/Core/Common/Common.vcxproj.filters
+++ b/Source/Core/Common/Common.vcxproj.filters
@@ -59,6 +59,7 @@
+
diff --git a/Source/Core/Common/Logging/Log.h b/Source/Core/Common/Logging/Log.h
index 6c50789b9d..c2dd70937e 100644
--- a/Source/Core/Common/Logging/Log.h
+++ b/Source/Core/Common/Logging/Log.h
@@ -31,7 +31,7 @@ enum LOG_TYPE
IOS,
IOS_DI,
IOS_ES,
- IOS_FILEIO,
+ IOS_FS,
IOS_NET,
IOS_SD,
IOS_SSL,
diff --git a/Source/Core/Common/Logging/LogManager.cpp b/Source/Core/Common/Logging/LogManager.cpp
index fcf606ad0b..7d910b3a8b 100644
--- a/Source/Core/Common/Logging/LogManager.cpp
+++ b/Source/Core/Common/Logging/LogManager.cpp
@@ -99,7 +99,7 @@ LogManager::LogManager()
m_log[LogTypes::IOS] = {"IOS", "IOS"};
m_log[LogTypes::IOS_DI] = {"IOS_DI", "IOS - Drive Interface"};
m_log[LogTypes::IOS_ES] = {"IOS_ES", "IOS - ETicket Services"};
- m_log[LogTypes::IOS_FILEIO] = {"IOS_FILEIO", "IOS - FileIO"};
+ m_log[LogTypes::IOS_FS] = {"IOS_FS", "IOS - Filesystem Services"};
m_log[LogTypes::IOS_SD] = {"IOS_SD", "IOS - SDIO"};
m_log[LogTypes::IOS_SSL] = {"IOS_SSL", "IOS - SSL"};
m_log[LogTypes::IOS_STM] = {"IOS_STM", "IOS - State Transition Manager"};
diff --git a/Source/Core/Common/Result.h b/Source/Core/Common/Result.h
new file mode 100644
index 0000000000..2c4f47b3d7
--- /dev/null
+++ b/Source/Core/Common/Result.h
@@ -0,0 +1,30 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+namespace Common
+{
+template
+class Result final
+{
+public:
+ Result(ResultCode code) : m_variant{code} {}
+ Result(const T& t) : m_variant{t} {}
+ Result(T&& t) : m_variant{std::move(t)} {}
+ explicit operator bool() const { return Succeeded(); }
+ bool Succeeded() const { return std::holds_alternative(m_variant); }
+ // Must only be called when Succeeded() returns false.
+ ResultCode Error() const { return std::get(m_variant); }
+ // Must only be called when Succeeded() returns true.
+ const T& operator*() const { return std::get(m_variant); }
+ const T* operator->() const { return &std::get(m_variant); }
+ T& operator*() { return std::get(m_variant); }
+ T* operator->() { return &std::get(m_variant); }
+private:
+ std::variant m_variant;
+};
+} // namespace Common
diff --git a/Source/Core/Common/Swap.h b/Source/Core/Common/Swap.h
index c5b143dbcb..207faac93c 100644
--- a/Source/Core/Common/Swap.h
+++ b/Source/Core/Common/Swap.h
@@ -166,4 +166,16 @@ inline T FromBigEndian(T data)
swap(reinterpret_cast(&data));
return data;
}
+
+template
+struct BigEndianValue
+{
+ static_assert(std::is_arithmetic(), "value_type must be an arithmetic type");
+ BigEndianValue() = default;
+ explicit BigEndianValue(value_type val) { *this = val; }
+ operator value_type() const { return FromBigEndian(raw); }
+ void operator=(value_type v) { raw = FromBigEndian(v); }
+private:
+ value_type raw;
+};
} // Namespace Common
diff --git a/Source/Core/Core/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Boot/Boot_WiiWAD.cpp
index 156c2698a8..111f87de3b 100644
--- a/Source/Core/Core/Boot/Boot_WiiWAD.cpp
+++ b/Source/Core/Core/Boot/Boot_WiiWAD.cpp
@@ -2,37 +2,67 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include
+#include
#include
#include
-#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
-#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
-#include "Common/NandPaths.h"
#include "Core/Boot/Boot.h"
#include "Core/CommonTitles.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
-#include "Core/IOS/FS/FileIO.h"
+#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/IOS.h"
#include "Core/WiiUtils.h"
#include "DiscIO/WiiWad.h"
+// cdb.vff is a virtual Fat filesystem created on first launch of sysmenu
+// we create it here as it is faster ~3 minutes for me when sysmenu does it
+// ~1 second created here
+static void CreateVirtualFATFilesystem(std::shared_ptr fs)
+{
+ constexpr u32 SYSMENU_UID = 0x1000;
+ constexpr u16 SYSMENU_GID = 0x1;
+
+ const std::string cdb_path = "/title/00000001/00000002/data/cdb.vff";
+ fs->CreateFile(SYSMENU_UID, SYSMENU_GID, cdb_path, 0, IOS::HLE::FS::Mode::ReadWrite,
+ IOS::HLE::FS::Mode::ReadWrite, IOS::HLE::FS::Mode::ReadWrite);
+
+ constexpr size_t CDB_SIZE = 0x01400000;
+ const auto metadata = fs->GetMetadata(SYSMENU_UID, SYSMENU_GID, cdb_path);
+ if (!metadata || metadata->size >= CDB_SIZE)
+ return;
+
+ const auto fd = fs->OpenFile(SYSMENU_UID, SYSMENU_GID, cdb_path, IOS::HLE::FS::Mode::Write);
+ if (!fd)
+ return;
+
+ constexpr u8 CDB_HEADER[0x20] = {'V', 'F', 'F', 0x20, 0xfe, 0xff, 1, 0, 1, 0x40, 0, 0, 0, 0x20};
+ constexpr u8 CDB_FAT[4] = {0xf0, 0xff, 0xff, 0xff};
+ std::vector data(CDB_SIZE);
+ std::copy_n(CDB_HEADER, sizeof(CDB_HEADER), data.begin());
+ std::copy_n(CDB_FAT, sizeof(CDB_FAT), data.begin() + sizeof(CDB_HEADER));
+ std::copy_n(CDB_FAT, sizeof(CDB_FAT), data.begin() + 0x14020);
+ // write the final 0 to 0 file from the second FAT to 20 MiB
+ data[CDB_SIZE - 1] = 0;
+ fs->WriteFile(*fd, data.data(), static_cast(data.size()));
+}
+
bool CBoot::BootNANDTitle(const u64 title_id)
{
UpdateStateFlags([](StateFlags* state) {
state->type = 0x04; // TYPE_NANDBOOT
});
+ auto* ios = IOS::HLE::GetIOS();
+
if (title_id == Titles::SYSTEM_MENU)
- IOS::HLE::CreateVirtualFATFilesystem();
+ CreateVirtualFATFilesystem(ios->GetFS());
SetupWiiMemory();
- auto* ios = IOS::HLE::GetIOS();
return ios->GetES()->LaunchTitle(title_id);
}
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 60d6d23769..aca7f15e81 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -165,8 +165,10 @@ add_library(core
IOS/ES/TitleInformation.cpp
IOS/ES/TitleManagement.cpp
IOS/ES/Views.cpp
- IOS/FS/FileIO.cpp
- IOS/FS/FS.cpp
+ IOS/FS/FileSystem.cpp
+ IOS/FS/FileSystemProxy.cpp
+ IOS/FS/HostBackend/File.cpp
+ IOS/FS/HostBackend/FS.cpp
IOS/Network/ICMPLin.cpp
IOS/Network/MACUtils.cpp
IOS/Network/Socket.cpp
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index 99f2b19876..641aaeaaab 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -195,8 +195,10 @@
-
-
+
+
+
+
@@ -445,8 +447,10 @@
-
-
+
+
+
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index 189b7d2088..5456cd4be5 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -732,7 +732,16 @@
IOS\DI
-
+
+ IOS\FS
+
+
+ IOS\FS
+
+
+ IOS\FS
+
+
IOS\FS
@@ -759,9 +768,6 @@
IOS\ES
-
- IOS\FS
-
IOS\Network
@@ -1401,15 +1407,21 @@
IOS\ES
-
+
+ IOS\FS
+
+
+ IOS\FS
+
+
+ IOS\FS
+
+
IOS\FS
IOS\ES
-
- IOS\FS
-
IOS\USB\Bluetooth
diff --git a/Source/Core/Core/IOS/Device.h b/Source/Core/Core/IOS/Device.h
index 46cb0d0479..32dc456037 100644
--- a/Source/Core/Core/IOS/Device.h
+++ b/Source/Core/Core/IOS/Device.h
@@ -173,7 +173,6 @@ public:
enum class DeviceType : u32
{
Static, // Devices which appear in s_device_map.
- FileIO, // FileIO devices which are created dynamically.
OH0, // OH0 child devices which are created dynamically.
};
diff --git a/Source/Core/Core/IOS/FS/FS.cpp b/Source/Core/Core/IOS/FS/FS.cpp
deleted file mode 100644
index b9c5889390..0000000000
--- a/Source/Core/Core/IOS/FS/FS.cpp
+++ /dev/null
@@ -1,650 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include "Core/IOS/FS/FS.h"
-
-#include
-#include
-#include
-#include
-#include
-
-#include "Common/Assert.h"
-#include "Common/ChunkFile.h"
-#include "Common/CommonPaths.h"
-#include "Common/CommonTypes.h"
-#include "Common/File.h"
-#include "Common/FileUtil.h"
-#include "Common/Logging/Log.h"
-#include "Common/MsgHandler.h"
-#include "Common/NandPaths.h"
-#include "Core/HW/Memmap.h"
-#include "Core/HW/SystemTimers.h"
-#include "Core/IOS/ES/ES.h"
-#include "Core/IOS/ES/Formats.h"
-#include "Core/IOS/FS/FileIO.h"
-
-namespace IOS
-{
-namespace HLE
-{
-static bool IsValidWiiPath(const std::string& path)
-{
- return path.compare(0, 1, "/") == 0;
-}
-
-namespace Device
-{
-FS::FS(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
-{
- const std::string tmp_dir = BuildFilename("/tmp");
- File::DeleteDirRecursively(tmp_dir);
- File::CreateDir(tmp_dir);
-}
-
-void FS::DoState(PointerWrap& p)
-{
- DoStateShared(p);
-
- // handle /tmp
-
- std::string Path = File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/tmp";
- if (p.GetMode() == PointerWrap::MODE_READ)
- {
- File::DeleteDirRecursively(Path);
- File::CreateDir(Path);
-
- // now restore from the stream
- while (1)
- {
- char type = 0;
- p.Do(type);
- if (!type)
- break;
- std::string filename;
- p.Do(filename);
- std::string name = Path + DIR_SEP + filename;
- switch (type)
- {
- case 'd':
- {
- File::CreateDir(name);
- break;
- }
- case 'f':
- {
- u32 size = 0;
- p.Do(size);
-
- File::IOFile handle(name, "wb");
- char buf[65536];
- u32 count = size;
- while (count > 65536)
- {
- p.DoArray(buf);
- handle.WriteArray(&buf[0], 65536);
- count -= 65536;
- }
- p.DoArray(&buf[0], count);
- handle.WriteArray(&buf[0], count);
- break;
- }
- }
- }
- }
- else
- {
- // recurse through tmp and save dirs and files
-
- File::FSTEntry parentEntry = File::ScanDirectoryTree(Path, true);
- std::deque todo;
- todo.insert(todo.end(), parentEntry.children.begin(), parentEntry.children.end());
-
- while (!todo.empty())
- {
- File::FSTEntry& entry = todo.front();
- std::string name = entry.physicalName;
- name.erase(0, Path.length() + 1);
- char type = entry.isDirectory ? 'd' : 'f';
- p.Do(type);
- p.Do(name);
- if (entry.isDirectory)
- {
- todo.insert(todo.end(), entry.children.begin(), entry.children.end());
- }
- else
- {
- u32 size = (u32)entry.size;
- p.Do(size);
-
- File::IOFile handle(entry.physicalName, "rb");
- char buf[65536];
- u32 count = size;
- while (count > 65536)
- {
- handle.ReadArray(&buf[0], 65536);
- p.DoArray(buf);
- count -= 65536;
- }
- handle.ReadArray(&buf[0], count);
- p.DoArray(&buf[0], count);
- }
- todo.pop_front();
- }
-
- char type = 0;
- p.Do(type);
- }
-}
-
-// Get total filesize of contents of a directory (recursive)
-// Only used for ES_GetUsage atm, could be useful elsewhere?
-static u64 ComputeTotalFileSize(const File::FSTEntry& parentEntry)
-{
- u64 sizeOfFiles = 0;
- for (const File::FSTEntry& entry : parentEntry.children)
- {
- if (entry.isDirectory)
- sizeOfFiles += ComputeTotalFileSize(entry);
- else
- sizeOfFiles += entry.size;
- }
- return sizeOfFiles;
-}
-
-IPCCommandResult FS::IOCtl(const IOCtlRequest& request)
-{
- Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
-
- switch (request.request)
- {
- case IOCTL_GET_STATS:
- return GetStats(request);
- case IOCTL_CREATE_DIR:
- return CreateDirectory(request);
- case IOCTL_SET_ATTR:
- return SetAttribute(request);
- case IOCTL_GET_ATTR:
- return GetAttribute(request);
- case IOCTL_DELETE_FILE:
- return DeleteFile(request);
- case IOCTL_RENAME_FILE:
- return RenameFile(request);
- case IOCTL_CREATE_FILE:
- return CreateFile(request);
- case IOCTL_SHUTDOWN:
- return Shutdown(request);
- default:
- request.DumpUnknown(GetDeviceName(), LogTypes::IOS_FILEIO);
- break;
- }
-
- return GetFSReply(FS_EINVAL);
-}
-
-IPCCommandResult FS::IOCtlV(const IOCtlVRequest& request)
-{
- switch (request.request)
- {
- case IOCTLV_READ_DIR:
- return ReadDirectory(request);
- case IOCTLV_GETUSAGE:
- return GetUsage(request);
- default:
- request.DumpUnknown(GetDeviceName(), LogTypes::IOS_FILEIO);
- break;
- }
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-// ~1/1000th of a second is too short and causes hangs in Wii Party
-// Play it safe at 1/500th
-IPCCommandResult FS::GetFSReply(const s32 return_value) const
-{
- return {return_value, true, SystemTimers::GetTicksPerSecond() / 500};
-}
-
-IPCCommandResult FS::GetStats(const IOCtlRequest& request)
-{
- if (request.buffer_out_size < 0x1c)
- return GetFSReply(-1017);
-
- WARN_LOG(IOS_FILEIO, "FS: GET STATS - returning static values for now");
-
- // TODO: scrape the real amounts from somewhere...
- NANDStat fs;
- fs.BlockSize = 0x4000;
- fs.FreeUserBlocks = 0x5DEC;
- fs.UsedUserBlocks = 0x1DD4;
- fs.FreeSysBlocks = 0x10;
- fs.UsedSysBlocks = 0x02F0;
- fs.Free_INodes = 0x146B;
- fs.Used_Inodes = 0x0394;
-
- std::memcpy(Memory::GetPointer(request.buffer_out), &fs, sizeof(NANDStat));
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::CreateDirectory(const IOCtlRequest& request)
-{
- DEBUG_ASSERT(request.buffer_out_size == 0);
- u32 Addr = request.buffer_in;
-
- u32 OwnerID = Memory::Read_U32(Addr);
- Addr += 4;
- u16 GroupID = Memory::Read_U16(Addr);
- Addr += 2;
-
- const std::string wii_path = Memory::GetString(Addr, 64);
- if (!IsValidWiiPath(wii_path))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", wii_path.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- std::string DirName(BuildFilename(wii_path));
- Addr += 64;
- Addr += 9; // owner attribs, permission
- u8 Attribs = Memory::Read_U8(Addr);
-
- INFO_LOG(IOS_FILEIO, "FS: CREATE_DIR %s, OwnerID %#x, GroupID %#x, Attributes %#x",
- DirName.c_str(), OwnerID, GroupID, Attribs);
-
- DirName += DIR_SEP;
- File::CreateFullPath(DirName);
- DEBUG_ASSERT_MSG(IOS_FILEIO, File::IsDirectory(DirName), "FS: CREATE_DIR %s failed",
- DirName.c_str());
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::SetAttribute(const IOCtlRequest& request)
-{
- u32 Addr = request.buffer_in;
-
- u32 OwnerID = Memory::Read_U32(Addr);
- Addr += 4;
- u16 GroupID = Memory::Read_U16(Addr);
- Addr += 2;
-
- const std::string wii_path = Memory::GetString(Addr, 64);
- if (!IsValidWiiPath(wii_path))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", wii_path.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- std::string Filename = BuildFilename(wii_path);
- Addr += 64;
- u8 OwnerPerm = Memory::Read_U8(Addr);
- Addr += 1;
- u8 GroupPerm = Memory::Read_U8(Addr);
- Addr += 1;
- u8 OtherPerm = Memory::Read_U8(Addr);
- Addr += 1;
- u8 Attributes = Memory::Read_U8(Addr);
- Addr += 1;
-
- INFO_LOG(IOS_FILEIO, "FS: SetAttrib %s", Filename.c_str());
- DEBUG_LOG(IOS_FILEIO, " OwnerID: 0x%08x", OwnerID);
- DEBUG_LOG(IOS_FILEIO, " GroupID: 0x%04x", GroupID);
- DEBUG_LOG(IOS_FILEIO, " OwnerPerm: 0x%02x", OwnerPerm);
- DEBUG_LOG(IOS_FILEIO, " GroupPerm: 0x%02x", GroupPerm);
- DEBUG_LOG(IOS_FILEIO, " OtherPerm: 0x%02x", OtherPerm);
- DEBUG_LOG(IOS_FILEIO, " Attributes: 0x%02x", Attributes);
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::GetAttribute(const IOCtlRequest& request)
-{
- DEBUG_ASSERT_MSG(IOS_FILEIO, request.buffer_out_size == 76,
- " GET_ATTR needs an 76 bytes large output buffer but it is %i bytes large",
- request.buffer_out_size);
-
- u32 OwnerID = 0;
- u16 GroupID = 0x3031; // this is also known as makercd, 01 (0x3031) for nintendo and 08
- // (0x3038) for MH3 etc
-
- const std::string wii_path = Memory::GetString(request.buffer_in, 64);
- if (!IsValidWiiPath(wii_path))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", wii_path.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- std::string Filename = BuildFilename(wii_path);
- u8 OwnerPerm = 0x3; // read/write
- u8 GroupPerm = 0x3; // read/write
- u8 OtherPerm = 0x3; // read/write
- u8 Attributes = 0x00; // no attributes
-
- // Hack: if the path that is being accessed is within an installed title directory, get the
- // UID/GID from the installed title TMD.
- u64 title_id;
- if (IsTitlePath(Filename, Common::FROM_SESSION_ROOT, &title_id))
- {
- IOS::ES::TMDReader tmd = GetIOS()->GetES()->FindInstalledTMD(title_id);
- if (tmd.IsValid())
- {
- GroupID = tmd.GetGroupId();
- }
- }
-
- if (File::IsDirectory(Filename))
- {
- INFO_LOG(IOS_FILEIO, "FS: GET_ATTR Directory %s - all permission flags are set",
- Filename.c_str());
- }
- else
- {
- if (File::Exists(Filename))
- {
- INFO_LOG(IOS_FILEIO, "FS: GET_ATTR %s - all permission flags are set", Filename.c_str());
- }
- else
- {
- INFO_LOG(IOS_FILEIO, "FS: GET_ATTR unknown %s", Filename.c_str());
- return GetFSReply(FS_ENOENT);
- }
- }
-
- // write answer to buffer
- if (request.buffer_out_size == 76)
- {
- u32 Addr = request.buffer_out;
- Memory::Write_U32(OwnerID, Addr);
- Addr += 4;
- Memory::Write_U16(GroupID, Addr);
- Addr += 2;
- memcpy(Memory::GetPointer(Addr), Memory::GetPointer(request.buffer_in), 64);
- Addr += 64;
- Memory::Write_U8(OwnerPerm, Addr);
- Addr += 1;
- Memory::Write_U8(GroupPerm, Addr);
- Addr += 1;
- Memory::Write_U8(OtherPerm, Addr);
- Addr += 1;
- Memory::Write_U8(Attributes, Addr);
- Addr += 1;
- }
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::DeleteFile(const IOCtlRequest& request)
-{
- DEBUG_ASSERT(request.buffer_out_size == 0);
- int Offset = 0;
-
- const std::string wii_path = Memory::GetString(request.buffer_in + Offset, 64);
- if (!IsValidWiiPath(wii_path))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", wii_path.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- std::string Filename = BuildFilename(wii_path);
- Offset += 64;
- if (File::Delete(Filename))
- {
- INFO_LOG(IOS_FILEIO, "FS: DeleteFile %s", Filename.c_str());
- }
- else if (File::DeleteDir(Filename))
- {
- INFO_LOG(IOS_FILEIO, "FS: DeleteDir %s", Filename.c_str());
- }
- else
- {
- WARN_LOG(IOS_FILEIO, "FS: DeleteFile %s - failed!!!", Filename.c_str());
- }
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::RenameFile(const IOCtlRequest& request)
-{
- DEBUG_ASSERT(request.buffer_out_size == 0);
- int Offset = 0;
-
- const std::string wii_path = Memory::GetString(request.buffer_in + Offset, 64);
- if (!IsValidWiiPath(wii_path))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", wii_path.c_str());
- return GetFSReply(FS_EINVAL);
- }
- std::string Filename = BuildFilename(wii_path);
- Offset += 64;
-
- const std::string wii_path_rename = Memory::GetString(request.buffer_in + Offset, 64);
- if (!IsValidWiiPath(wii_path_rename))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", wii_path_rename.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- std::string FilenameRename = BuildFilename(wii_path_rename);
- Offset += 64;
-
- // try to make the basis directory
- File::CreateFullPath(FilenameRename);
-
- // if there is already a file, delete it
- if (File::Exists(Filename) && File::Exists(FilenameRename))
- {
- File::Delete(FilenameRename);
- }
-
- // finally try to rename the file
- if (File::Rename(Filename, FilenameRename))
- {
- INFO_LOG(IOS_FILEIO, "FS: Rename %s to %s", Filename.c_str(), FilenameRename.c_str());
- }
- else
- {
- ERROR_LOG(IOS_FILEIO, "FS: Rename %s to %s - failed", Filename.c_str(), FilenameRename.c_str());
- return GetFSReply(FS_ENOENT);
- }
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::CreateFile(const IOCtlRequest& request)
-{
- DEBUG_ASSERT(request.buffer_out_size == 0);
-
- u32 Addr = request.buffer_in;
- u32 OwnerID = Memory::Read_U32(Addr);
- Addr += 4;
- u16 GroupID = Memory::Read_U16(Addr);
- Addr += 2;
-
- const std::string wii_path = Memory::GetString(Addr, 64);
- if (!IsValidWiiPath(wii_path))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", wii_path.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- std::string Filename(BuildFilename(wii_path));
- Addr += 64;
- u8 OwnerPerm = Memory::Read_U8(Addr);
- Addr++;
- u8 GroupPerm = Memory::Read_U8(Addr);
- Addr++;
- u8 OtherPerm = Memory::Read_U8(Addr);
- Addr++;
- u8 Attributes = Memory::Read_U8(Addr);
- Addr++;
-
- INFO_LOG(IOS_FILEIO, "FS: CreateFile %s", Filename.c_str());
- DEBUG_LOG(IOS_FILEIO, " OwnerID: 0x%08x", OwnerID);
- DEBUG_LOG(IOS_FILEIO, " GroupID: 0x%04x", GroupID);
- DEBUG_LOG(IOS_FILEIO, " OwnerPerm: 0x%02x", OwnerPerm);
- DEBUG_LOG(IOS_FILEIO, " GroupPerm: 0x%02x", GroupPerm);
- DEBUG_LOG(IOS_FILEIO, " OtherPerm: 0x%02x", OtherPerm);
- DEBUG_LOG(IOS_FILEIO, " Attributes: 0x%02x", Attributes);
-
- // check if the file already exist
- if (File::Exists(Filename))
- {
- INFO_LOG(IOS_FILEIO, "\tresult = FS_EEXIST");
- return GetFSReply(FS_EEXIST);
- }
-
- // create the file
- File::CreateFullPath(Filename); // just to be sure
- bool Result = File::CreateEmptyFile(Filename);
- if (!Result)
- {
- ERROR_LOG(IOS_FILEIO, "FS: couldn't create new file");
- PanicAlert("FS: couldn't create new file");
- return GetFSReply(FS_EINVAL);
- }
-
- INFO_LOG(IOS_FILEIO, "\tresult = IPC_SUCCESS");
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::Shutdown(const IOCtlRequest& request)
-{
- // TODO: stop emulation
- INFO_LOG(IOS_FILEIO, "Wii called Shutdown()");
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::ReadDirectory(const IOCtlVRequest& request)
-{
- const std::string relative_path =
- Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
-
- if (!IsValidWiiPath(relative_path))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", relative_path.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- // the Wii uses this function to define the type (dir or file)
- std::string DirName(BuildFilename(relative_path));
-
- INFO_LOG(IOS_FILEIO, "FS: IOCTL_READ_DIR %s", DirName.c_str());
-
- const File::FileInfo file_info(DirName);
-
- if (!file_info.Exists())
- {
- WARN_LOG(IOS_FILEIO, "FS: Search not found: %s", DirName.c_str());
- return GetFSReply(FS_ENOENT);
- }
-
- if (!file_info.IsDirectory())
- {
- // It's not a directory, so error.
- // Games don't usually seem to care WHICH error they get, as long as it's <
- // Well the system menu CARES!
- WARN_LOG(IOS_FILEIO, "\tNot a directory - return FS_EINVAL");
- return GetFSReply(FS_EINVAL);
- }
-
- File::FSTEntry entry = File::ScanDirectoryTree(DirName, false);
-
- // it is one
- if ((request.in_vectors.size() == 1) && (request.io_vectors.size() == 1))
- {
- size_t numFile = entry.children.size();
- INFO_LOG(IOS_FILEIO, "\t%zu files found", numFile);
-
- Memory::Write_U32((u32)numFile, request.io_vectors[0].address);
- }
- else
- {
- for (File::FSTEntry& child : entry.children)
- {
- // Decode escaped invalid file system characters so that games (such as
- // Harry Potter and the Half-Blood Prince) can find what they expect.
- child.virtualName = Common::UnescapeFileName(child.virtualName);
- }
-
- std::sort(entry.children.begin(), entry.children.end(),
- [](const File::FSTEntry& one, const File::FSTEntry& two) {
- return one.virtualName < two.virtualName;
- });
-
- u32 MaxEntries = Memory::Read_U32(request.in_vectors[0].address);
-
- memset(Memory::GetPointer(request.io_vectors[0].address), 0, request.io_vectors[0].size);
-
- size_t numFiles = 0;
- char* pFilename = (char*)Memory::GetPointer((u32)(request.io_vectors[0].address));
-
- for (size_t i = 0; i < entry.children.size() && i < MaxEntries; i++)
- {
- const std::string& FileName = entry.children[i].virtualName;
-
- strcpy(pFilename, FileName.c_str());
- pFilename += FileName.length();
- *pFilename++ = 0x00; // termination
- numFiles++;
-
- INFO_LOG(IOS_FILEIO, "\tFound: %s", FileName.c_str());
- }
-
- Memory::Write_U32((u32)numFiles, request.io_vectors[1].address);
- }
-
- return GetFSReply(IPC_SUCCESS);
-}
-
-IPCCommandResult FS::GetUsage(const IOCtlVRequest& request)
-{
- DEBUG_ASSERT(request.io_vectors.size() == 2);
- DEBUG_ASSERT(request.io_vectors[0].size == 4);
- DEBUG_ASSERT(request.io_vectors[1].size == 4);
-
- // this command sucks because it asks of the number of used
- // fsBlocks and inodes
- // It should be correct, but don't count on it...
- std::string relativepath =
- Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
-
- if (!IsValidWiiPath(relativepath))
- {
- WARN_LOG(IOS_FILEIO, "Not a valid path: %s", relativepath.c_str());
- return GetFSReply(FS_EINVAL);
- }
-
- std::string path(BuildFilename(relativepath));
- u32 fsBlocks = 0;
- u32 iNodes = 0;
-
- INFO_LOG(IOS_FILEIO, "IOCTL_GETUSAGE %s", path.c_str());
- if (File::IsDirectory(path))
- {
- File::FSTEntry parentDir = File::ScanDirectoryTree(path, true);
- // add one for the folder itself
- iNodes = 1 + (u32)parentDir.size;
-
- u64 totalSize = ComputeTotalFileSize(parentDir); // "Real" size, to be converted to nand blocks
-
- fsBlocks = (u32)(totalSize / (16 * 1024)); // one bock is 16kb
-
- INFO_LOG(IOS_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes);
- }
- else
- {
- fsBlocks = 0;
- iNodes = 0;
- WARN_LOG(IOS_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str());
- }
-
- Memory::Write_U32(fsBlocks, request.io_vectors[0].address);
- Memory::Write_U32(iNodes, request.io_vectors[1].address);
-
- return GetFSReply(IPC_SUCCESS);
-}
-} // namespace Device
-} // namespace HLE
-} // namespace IOS
diff --git a/Source/Core/Core/IOS/FS/FS.h b/Source/Core/Core/IOS/FS/FS.h
deleted file mode 100644
index 0859e874cb..0000000000
--- a/Source/Core/Core/IOS/FS/FS.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include
-
-#include "Common/CommonTypes.h"
-#include "Core/IOS/Device.h"
-#include "Core/IOS/IOS.h"
-
-class PointerWrap;
-
-namespace IOS
-{
-namespace HLE
-{
-struct NANDStat
-{
- u32 BlockSize;
- u32 FreeUserBlocks;
- u32 UsedUserBlocks;
- u32 FreeSysBlocks;
- u32 UsedSysBlocks;
- u32 Free_INodes;
- u32 Used_Inodes;
-};
-
-namespace Device
-{
-class FS : public Device
-{
-public:
- FS(Kernel& ios, const std::string& device_name);
-
- void DoState(PointerWrap& p) override;
-
- IPCCommandResult IOCtl(const IOCtlRequest& request) override;
- IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
-
-private:
- enum
- {
- IOCTL_GET_STATS = 0x02,
- IOCTL_CREATE_DIR = 0x03,
- IOCTLV_READ_DIR = 0x04,
- IOCTL_SET_ATTR = 0x05,
- IOCTL_GET_ATTR = 0x06,
- IOCTL_DELETE_FILE = 0x07,
- IOCTL_RENAME_FILE = 0x08,
- IOCTL_CREATE_FILE = 0x09,
- IOCTLV_GETUSAGE = 0x0C,
- IOCTL_SHUTDOWN = 0x0D
- };
-
- IPCCommandResult GetFSReply(s32 return_value) const;
-
- IPCCommandResult GetStats(const IOCtlRequest& request);
- IPCCommandResult CreateDirectory(const IOCtlRequest& request);
- IPCCommandResult SetAttribute(const IOCtlRequest& request);
- IPCCommandResult GetAttribute(const IOCtlRequest& request);
- IPCCommandResult DeleteFile(const IOCtlRequest& request);
- IPCCommandResult RenameFile(const IOCtlRequest& request);
- IPCCommandResult CreateFile(const IOCtlRequest& request);
- IPCCommandResult Shutdown(const IOCtlRequest& request);
-
- IPCCommandResult ReadDirectory(const IOCtlVRequest& request);
- IPCCommandResult GetUsage(const IOCtlVRequest& request);
-};
-} // namespace Device
-} // namespace HLE
-} // namespace IOS
diff --git a/Source/Core/Core/IOS/FS/FileIO.cpp b/Source/Core/Core/IOS/FS/FileIO.cpp
deleted file mode 100644
index d7e3cb3f44..0000000000
--- a/Source/Core/Core/IOS/FS/FileIO.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include "Core/IOS/FS/FileIO.h"
-
-#include
-#include
-#include