From 687c99cab61cf7ff91cae2fb0ea2750b2ed4c2b2 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Sun, 29 Jan 2023 01:27:27 +0200 Subject: [PATCH] [FS] Add DeleteFile --- include/fs/archive_base.hpp | 7 +++++++ include/fs/archive_ext_save_data.hpp | 4 +++- include/fs/archive_ncch.hpp | 4 +++- include/fs/archive_save_data.hpp | 4 +++- include/fs/archive_sdmc.hpp | 4 +++- include/fs/archive_self_ncch.hpp | 4 +++- include/services/fs.hpp | 1 + src/core/fs/archive_ext_save_data.cpp | 16 ++++++++++++++++ src/core/fs/archive_ncch.cpp | 5 +++++ src/core/fs/archive_save_data.cpp | 5 +++++ src/core/fs/archive_sdmc.cpp | 5 +++++ src/core/fs/archive_self_ncch.cpp | 5 +++++ src/core/services/fs.cpp | 26 +++++++++++++++++++++++++- 13 files changed, 84 insertions(+), 6 deletions(-) diff --git a/include/fs/archive_base.hpp b/include/fs/archive_base.hpp index e396472e..b053b0f4 100644 --- a/include/fs/archive_base.hpp +++ b/include/fs/archive_base.hpp @@ -115,6 +115,11 @@ enum class CreateFileResult : u32 { FileTooLarge = 0x86044D2 }; +enum class DeleteFileResult : u32 { + Success = 0, + FileNotFound = 0xC8804470 +}; + class ArchiveBase { protected: using Handle = u32; @@ -172,6 +177,8 @@ public: virtual std::string name() = 0; virtual u64 getFreeBytes() = 0; virtual CreateFileResult createFile(const FSPath& path, u64 size) = 0; + virtual DeleteFileResult deleteFile(const FSPath& path) = 0; + // Returns nullopt if opening the file failed, otherwise returns a file descriptor to it (nullptr if none is needed) virtual FileDescriptor openFile(const FSPath& path, const FilePerms& perms) = 0; diff --git a/include/fs/archive_ext_save_data.hpp b/include/fs/archive_ext_save_data.hpp index 40ddbb54..b12ce1c9 100644 --- a/include/fs/archive_ext_save_data.hpp +++ b/include/fs/archive_ext_save_data.hpp @@ -8,8 +8,10 @@ public: u64 getFreeBytes() override { Helpers::panic("ExtSaveData::GetFreeBytes unimplemented"); return 0; } std::string name() override { return "ExtSaveData"; } - ArchiveBase* openArchive(const FSPath& path) override; CreateFileResult createFile(const FSPath& path, u64 size) override; + DeleteFileResult deleteFile(const FSPath& path) override; + + ArchiveBase* openArchive(const FSPath& path) override; FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override; std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override; diff --git a/include/fs/archive_ncch.hpp b/include/fs/archive_ncch.hpp index 175d3539..558c8175 100644 --- a/include/fs/archive_ncch.hpp +++ b/include/fs/archive_ncch.hpp @@ -8,8 +8,10 @@ public: u64 getFreeBytes() override { Helpers::panic("NCCH::GetFreeBytes unimplemented"); return 0; } std::string name() override { return "NCCH"; } - ArchiveBase* openArchive(const FSPath& path) override; CreateFileResult createFile(const FSPath& path, u64 size) override; + DeleteFileResult deleteFile(const FSPath& path) override; + + ArchiveBase* openArchive(const FSPath& path) override; FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override; std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override; diff --git a/include/fs/archive_save_data.hpp b/include/fs/archive_save_data.hpp index 2e5d070b..824924cd 100644 --- a/include/fs/archive_save_data.hpp +++ b/include/fs/archive_save_data.hpp @@ -8,8 +8,10 @@ public: u64 getFreeBytes() override { Helpers::panic("SaveData::GetFreeBytes unimplemented"); return 0; } std::string name() override { return "SaveData"; } - ArchiveBase* openArchive(const FSPath& path) override; CreateFileResult createFile(const FSPath& path, u64 size) override; + DeleteFileResult deleteFile(const FSPath& path) override; + + ArchiveBase* openArchive(const FSPath& path) override; FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override; std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override; diff --git a/include/fs/archive_sdmc.hpp b/include/fs/archive_sdmc.hpp index 83aa1717..b772aedc 100644 --- a/include/fs/archive_sdmc.hpp +++ b/include/fs/archive_sdmc.hpp @@ -8,8 +8,10 @@ public: u64 getFreeBytes() override { Helpers::panic("SDMC::GetFreeBytes unimplemented"); return 0; } std::string name() override { return "SDMC"; } - ArchiveBase* openArchive(const FSPath& path) override; CreateFileResult createFile(const FSPath& path, u64 size) override; + DeleteFileResult deleteFile(const FSPath& path) override; + + ArchiveBase* openArchive(const FSPath& path) override; FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override; std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override; }; \ No newline at end of file diff --git a/include/fs/archive_self_ncch.hpp b/include/fs/archive_self_ncch.hpp index d76513e3..5e325f91 100644 --- a/include/fs/archive_self_ncch.hpp +++ b/include/fs/archive_self_ncch.hpp @@ -8,8 +8,10 @@ public: u64 getFreeBytes() override { return 0; } std::string name() override { return "SelfNCCH"; } - ArchiveBase* openArchive(const FSPath& path) override; CreateFileResult createFile(const FSPath& path, u64 size) override; + DeleteFileResult deleteFile(const FSPath& path) override; + + ArchiveBase* openArchive(const FSPath& path) override; FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override; std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override; diff --git a/include/services/fs.hpp b/include/services/fs.hpp index 047cca25..40555e89 100644 --- a/include/services/fs.hpp +++ b/include/services/fs.hpp @@ -34,6 +34,7 @@ class FSService { // Service commands void createFile(u32 messagePointer); void closeArchive(u32 messagePointer); + void deleteFile(u32 messagePointer); void getPriority(u32 messagePointer); void initialize(u32 messagePointer); void initializeWithSdkVersion(u32 messagePointer); diff --git a/src/core/fs/archive_ext_save_data.cpp b/src/core/fs/archive_ext_save_data.cpp index b2da8adc..30717ff7 100644 --- a/src/core/fs/archive_ext_save_data.cpp +++ b/src/core/fs/archive_ext_save_data.cpp @@ -30,6 +30,22 @@ CreateFileResult ExtSaveDataArchive::createFile(const FSPath& path, u64 size) { return CreateFileResult::Success; } +DeleteFileResult ExtSaveDataArchive::deleteFile(const FSPath& path) { + if (path.type == PathType::UTF16) { + if (!isPathSafe(path)) + Helpers::panic("Unsafe path in ExtSaveData::DeleteFile"); + + fs::path p = IOFile::getAppData() / "NAND"; + p += fs::path(path.utf16_string).make_preferred(); + + bool success = fs::remove(p); + return success ? DeleteFileResult::Success : DeleteFileResult::FileNotFound; + } + + Helpers::panic("ExtSaveDataArchive::DeleteFile: Failed"); + return DeleteFileResult::Success; +} + FileDescriptor ExtSaveDataArchive::openFile(const FSPath& path, const FilePerms& perms) { if (path.type == PathType::UTF16) { if (!isPathSafe(path)) diff --git a/src/core/fs/archive_ncch.cpp b/src/core/fs/archive_ncch.cpp index a8016c30..67954f23 100644 --- a/src/core/fs/archive_ncch.cpp +++ b/src/core/fs/archive_ncch.cpp @@ -24,6 +24,11 @@ CreateFileResult NCCHArchive::createFile(const FSPath& path, u64 size) { return CreateFileResult::Success; } +DeleteFileResult NCCHArchive::deleteFile(const FSPath& path) { + Helpers::panic("[NCCH] Unimplemented DeleteFile"); + return DeleteFileResult::Success; +} + FileDescriptor NCCHArchive::openFile(const FSPath& path, const FilePerms& perms) { if (path.type != PathType::Binary || path.binary.size() != 20) { Helpers::panic("NCCHArchive::OpenFile: Invalid path"); diff --git a/src/core/fs/archive_save_data.cpp b/src/core/fs/archive_save_data.cpp index 36e221ac..7f7aabcf 100644 --- a/src/core/fs/archive_save_data.cpp +++ b/src/core/fs/archive_save_data.cpp @@ -7,6 +7,11 @@ CreateFileResult SaveDataArchive::createFile(const FSPath& path, u64 size) { return CreateFileResult::Success; } +DeleteFileResult SaveDataArchive::deleteFile(const FSPath& path) { + Helpers::panic("[SaveData] Unimplemented DeleteFile"); + return DeleteFileResult::Success; +} + FileDescriptor SaveDataArchive::openFile(const FSPath& path, const FilePerms& perms) { if (!cartHasSaveData()) { printf("Tried to read SaveData FS without save data\n"); diff --git a/src/core/fs/archive_sdmc.cpp b/src/core/fs/archive_sdmc.cpp index f3bbc008..b78da522 100644 --- a/src/core/fs/archive_sdmc.cpp +++ b/src/core/fs/archive_sdmc.cpp @@ -6,6 +6,11 @@ CreateFileResult SDMCArchive::createFile(const FSPath& path, u64 size) { return CreateFileResult::Success; } +DeleteFileResult SDMCArchive::deleteFile(const FSPath& path) { + Helpers::panic("[SDMC] Unimplemented DeleteFile"); + return DeleteFileResult::Success; +} + FileDescriptor SDMCArchive::openFile(const FSPath& path, const FilePerms& perms) { printf("SDMCArchive::OpenFile: Failed"); return FileError; diff --git a/src/core/fs/archive_self_ncch.cpp b/src/core/fs/archive_self_ncch.cpp index e7990844..a6b12be7 100644 --- a/src/core/fs/archive_self_ncch.cpp +++ b/src/core/fs/archive_self_ncch.cpp @@ -14,6 +14,11 @@ CreateFileResult SelfNCCHArchive::createFile(const FSPath& path, u64 size) { return CreateFileResult::Success; } +DeleteFileResult SelfNCCHArchive::deleteFile(const FSPath& path) { + Helpers::panic("[SelfNCCH] Unimplemented DeleteFile"); + return DeleteFileResult::Success; +} + FileDescriptor SelfNCCHArchive::openFile(const FSPath& path, const FilePerms& perms) { if (!hasRomFS()) { printf("Tried to open a SelfNCCH file without a RomFS\n"); diff --git a/src/core/services/fs.cpp b/src/core/services/fs.cpp index 3d1b2648..50a46e26 100644 --- a/src/core/services/fs.cpp +++ b/src/core/services/fs.cpp @@ -2,8 +2,9 @@ #include "kernel/kernel.hpp" #include "io_file.hpp" -#ifdef CreateFile // windows.h defines this because of course it does. +#ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does. #undef CreateFile +#undef DeleteFile #endif namespace FSCommands { @@ -11,6 +12,7 @@ namespace FSCommands { Initialize = 0x08010002, OpenFile = 0x080201C2, OpenFileDirectly = 0x08030204, + DeleteFile = 0x08040142, CreateFile = 0x08080202, OpenArchive = 0x080C00C2, CloseArchive = 0x080E0080, @@ -106,6 +108,7 @@ void FSService::handleSyncRequest(u32 messagePointer) { switch (command) { case FSCommands::CreateFile: createFile(messagePointer); break; case FSCommands::CloseArchive: closeArchive(messagePointer); break; + case FSCommands::DeleteFile: deleteFile(messagePointer); break; case FSCommands::GetPriority: getPriority(messagePointer); break; case FSCommands::Initialize: initialize(messagePointer); break; case FSCommands::InitializeWithSdkVersion: initializeWithSdkVersion(messagePointer); break; @@ -258,6 +261,27 @@ void FSService::createFile(u32 messagePointer) { mem.write32(messagePointer + 4, static_cast(res)); } +void FSService::deleteFile(u32 messagePointer) { + const u32 archiveHandle = mem.read64(messagePointer + 8); + const u32 filePathType = mem.read32(messagePointer + 16); + const u32 filePathSize = mem.read32(messagePointer + 20); + const u32 filePathPointer = mem.read32(messagePointer + 28); + + log("FS::DeleteFile\n"); + auto archiveObject = kernel.getObject(archiveHandle, KernelObjectType::Archive); + if (archiveObject == nullptr) [[unlikely]] { + log("FS::OpenFile: Invalid archive handle %d\n", archiveHandle); + mem.write32(messagePointer + 4, Result::Failure); + return; + } + + ArchiveBase* archive = archiveObject->getData()->archive; + auto filePath = readPath(filePathType, filePathPointer, filePathSize); + + DeleteFileResult res = archive->deleteFile(filePath); + mem.write32(messagePointer + 4, static_cast(res)); +} + void FSService::getPriority(u32 messagePointer) { log("FS::GetPriority\n");