From 1f658f9b325709cf77191b4f7b642a20ce588cc9 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Sun, 28 Mar 2021 10:35:57 +0200 Subject: [PATCH] [XAM/Content] Prevent deletion of open packages --- src/xenia/kernel/xam/content_manager.cc | 13 +++++++++++++ src/xenia/kernel/xam/content_manager.h | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/src/xenia/kernel/xam/content_manager.cc b/src/xenia/kernel/xam/content_manager.cc index 105ff7422..9c08ac737 100644 --- a/src/xenia/kernel/xam/content_manager.cc +++ b/src/xenia/kernel/xam/content_manager.cc @@ -34,6 +34,7 @@ ContentPackage::ContentPackage(KernelState* kernel_state, const std::filesystem::path& package_path) : kernel_state_(kernel_state), root_name_(root_name) { device_path_ = fmt::format("\\Device\\Content\\{0}\\", ++content_device_id_); + content_data_ = data; auto fs = kernel_state_->file_system(); auto device = @@ -242,6 +243,11 @@ X_RESULT ContentManager::SetContentThumbnail(const ContentData& data, X_RESULT ContentManager::DeleteContent(const ContentData& data) { auto global_lock = global_critical_region_.Acquire(); + if (IsContentOpen(data)) { + // TODO(Gliniak): Get real error code for this case. + return X_ERROR_ACCESS_DENIED; + } + auto package_path = ResolvePackagePath(data); if (std::filesystem::remove_all(package_path) > 0) { return X_ERROR_SUCCESS; @@ -259,6 +265,13 @@ std::filesystem::path ContentManager::ResolveGameUserContentPath() { return root_path_ / title_id / kGameUserContentDirName / user_name; } +bool ContentManager::IsContentOpen(const ContentData& data) const { + return std::any_of(open_packages_.cbegin(), open_packages_.cend(), + [data](std::pair content) { + return data == content.second->GetPackageContentData(); + }); +} + } // namespace xam } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xam/content_manager.h b/src/xenia/kernel/xam/content_manager.h index a69c63592..e6f6f7e12 100644 --- a/src/xenia/kernel/xam/content_manager.h +++ b/src/xenia/kernel/xam/content_manager.h @@ -64,6 +64,11 @@ struct ContentData { ContentData() = default; + bool operator==(const ContentData& rhs) const { + return device_id == rhs.device_id && content_type == rhs.content_type && + file_name == rhs.file_name; + } + explicit ContentData(const XCONTENT_DATA& data) { device_id = data.device_id; content_type = data.content_type; @@ -120,10 +125,13 @@ class ContentPackage { const std::filesystem::path& package_path); ~ContentPackage(); + const ContentData& GetPackageContentData() const { return content_data_; } + private: KernelState* kernel_state_; std::string root_name_; std::string device_path_; + ContentData content_data_; }; class ContentManager { @@ -150,6 +158,7 @@ class ContentManager { std::vector buffer); X_RESULT DeleteContent(const ContentData& data); std::filesystem::path ResolveGameUserContentPath(); + bool IsContentOpen(const ContentData& data) const; private: std::filesystem::path ResolvePackageRoot(uint32_t content_type);