From 96b0e9476bdd010051bec427d365b49437801f4d Mon Sep 17 00:00:00 2001 From: wwylele Date: Sun, 2 Oct 2016 11:29:04 +0800 Subject: [PATCH] fs: implement DeleteDirectoryRecursively --- src/core/file_sys/archive_backend.h | 7 +++++++ src/core/file_sys/disk_archive.cpp | 4 ++++ src/core/file_sys/disk_archive.h | 1 + src/core/file_sys/ivfc_archive.cpp | 6 ++++++ src/core/file_sys/ivfc_archive.h | 1 + src/core/hle/service/fs/archive.cpp | 12 +++++++++++ src/core/hle/service/fs/archive.h | 9 +++++++++ src/core/hle/service/fs/fs_user.cpp | 31 ++++++++++++++++++++++++++++- 8 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h index d69c3c7851..06b8f2ed77 100644 --- a/src/core/file_sys/archive_backend.h +++ b/src/core/file_sys/archive_backend.h @@ -111,6 +111,13 @@ public: */ virtual bool DeleteDirectory(const Path& path) const = 0; + /** + * Delete a directory specified by its path and anything under it + * @param path Path relative to the archive + * @return Whether the directory could be deleted + */ + virtual bool DeleteDirectoryRecursively(const Path& path) const = 0; + /** * Create a file specified by its path * @param path Path relative to the Archive diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index 0f66998e13..2f05af3616 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp @@ -51,6 +51,10 @@ bool DiskArchive::DeleteDirectory(const Path& path) const { return FileUtil::DeleteDir(mount_point + path.AsString()); } +bool DiskArchive::DeleteDirectoryRecursively(const Path& path) const { + return FileUtil::DeleteDirRecursively(mount_point + path.AsString()); +} + ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const { std::string full_path = mount_point + path.AsString(); diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h index 2165f27f9b..59ebb20021 100644 --- a/src/core/file_sys/disk_archive.h +++ b/src/core/file_sys/disk_archive.h @@ -38,6 +38,7 @@ public: ResultCode DeleteFile(const Path& path) const override; bool RenameFile(const Path& src_path, const Path& dest_path) const override; bool DeleteDirectory(const Path& path) const override; + bool DeleteDirectoryRecursively(const Path& path) const override; ResultCode CreateFile(const Path& path, u64 size) const override; bool CreateDirectory(const Path& path) const override; bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index 49cc1de100..af59d296d7 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp @@ -43,6 +43,12 @@ bool IVFCArchive::DeleteDirectory(const Path& path) const { return false; } +bool IVFCArchive::DeleteDirectoryRecursively(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", + GetName().c_str()); + return false; +} + ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", GetName().c_str()); diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h index 0df6cf83aa..2fbb3a568f 100644 --- a/src/core/file_sys/ivfc_archive.h +++ b/src/core/file_sys/ivfc_archive.h @@ -37,6 +37,7 @@ public: ResultCode DeleteFile(const Path& path) const override; bool RenameFile(const Path& src_path, const Path& dest_path) const override; bool DeleteDirectory(const Path& path) const override; + bool DeleteDirectoryRecursively(const Path& path) const override; ResultCode CreateFile(const Path& path, u64 size) const override; bool CreateDirectory(const Path& path) const override; bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 4dc7e1e3c0..7f9696bfb2 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -362,6 +362,18 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy ErrorSummary::Canceled, ErrorLevel::Status); } +ResultCode DeleteDirectoryRecursivelyFromArchive(ArchiveHandle archive_handle, + const FileSys::Path& path) { + ArchiveBackend* archive = GetArchive(archive_handle); + if (archive == nullptr) + return ERR_INVALID_ARCHIVE_HANDLE; + + if (archive->DeleteDirectoryRecursively(path)) + return RESULT_SUCCESS; + return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description + ErrorSummary::Canceled, ErrorLevel::Status); +} + ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size) { ArchiveBackend* archive = GetArchive(archive_handle); diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 533be34a46..41a76285cd 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -132,6 +132,15 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, */ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); +/** + * Delete a Directory and anything under it from an Archive + * @param archive_handle Handle to an open Archive object + * @param path Path to the Directory inside of the Archive + * @return Whether deletion succeeded + */ +ResultCode DeleteDirectoryRecursivelyFromArchive(ArchiveHandle archive_handle, + const FileSys::Path& path); + /** * Create a File in an Archive * @param archive_handle Handle to an open Archive object diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 94f053dc23..582591e40c 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -234,6 +234,35 @@ static void DeleteDirectory(Service::Interface* self) { cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; } +/* + * FS_User::DeleteDirectoryRecursively service function + * Inputs: + * 0 : Command header 0x08070142 + * 1 : Transaction + * 2 : Archive handle lower word + * 3 : Archive handle upper word + * 4 : Directory path string type + * 5 : Directory path string size + * 7 : Directory path string data + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +static void DeleteDirectoryRecursively(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); + auto dirname_type = static_cast(cmd_buff[4]); + u32 dirname_size = cmd_buff[5]; + u32 dirname_ptr = cmd_buff[7]; + + FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); + + LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, + dir_path.DebugStr().c_str()); + + cmd_buff[1] = DeleteDirectoryRecursivelyFromArchive(archive_handle, dir_path).raw; +} + /* * FS_User::CreateFile service function * Inputs: @@ -868,7 +897,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x08040142, DeleteFile, "DeleteFile"}, {0x08050244, RenameFile, "RenameFile"}, {0x08060142, DeleteDirectory, "DeleteDirectory"}, - {0x08070142, nullptr, "DeleteDirectoryRecursively"}, + {0x08070142, DeleteDirectoryRecursively, "DeleteDirectoryRecursively"}, {0x08080202, CreateFile, "CreateFile"}, {0x08090182, CreateDirectory, "CreateDirectory"}, {0x080A0244, RenameDirectory, "RenameDirectory"},