[XAM/Content] Prevent deletion of open packages

This commit is contained in:
Gliniak 2021-03-28 10:35:57 +02:00 committed by Rick Gibbed
parent a18f9c9dc1
commit 1f658f9b32
2 changed files with 22 additions and 0 deletions

View File

@ -34,6 +34,7 @@ ContentPackage::ContentPackage(KernelState* kernel_state,
const std::filesystem::path& package_path) const std::filesystem::path& package_path)
: kernel_state_(kernel_state), root_name_(root_name) { : kernel_state_(kernel_state), root_name_(root_name) {
device_path_ = fmt::format("\\Device\\Content\\{0}\\", ++content_device_id_); device_path_ = fmt::format("\\Device\\Content\\{0}\\", ++content_device_id_);
content_data_ = data;
auto fs = kernel_state_->file_system(); auto fs = kernel_state_->file_system();
auto device = auto device =
@ -242,6 +243,11 @@ X_RESULT ContentManager::SetContentThumbnail(const ContentData& data,
X_RESULT ContentManager::DeleteContent(const ContentData& data) { X_RESULT ContentManager::DeleteContent(const ContentData& data) {
auto global_lock = global_critical_region_.Acquire(); 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); auto package_path = ResolvePackagePath(data);
if (std::filesystem::remove_all(package_path) > 0) { if (std::filesystem::remove_all(package_path) > 0) {
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
@ -259,6 +265,13 @@ std::filesystem::path ContentManager::ResolveGameUserContentPath() {
return root_path_ / title_id / kGameUserContentDirName / user_name; 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<string_key, ContentPackage*> content) {
return data == content.second->GetPackageContentData();
});
}
} // namespace xam } // namespace xam
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe

View File

@ -64,6 +64,11 @@ struct ContentData {
ContentData() = default; 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) { explicit ContentData(const XCONTENT_DATA& data) {
device_id = data.device_id; device_id = data.device_id;
content_type = data.content_type; content_type = data.content_type;
@ -120,10 +125,13 @@ class ContentPackage {
const std::filesystem::path& package_path); const std::filesystem::path& package_path);
~ContentPackage(); ~ContentPackage();
const ContentData& GetPackageContentData() const { return content_data_; }
private: private:
KernelState* kernel_state_; KernelState* kernel_state_;
std::string root_name_; std::string root_name_;
std::string device_path_; std::string device_path_;
ContentData content_data_;
}; };
class ContentManager { class ContentManager {
@ -150,6 +158,7 @@ class ContentManager {
std::vector<uint8_t> buffer); std::vector<uint8_t> buffer);
X_RESULT DeleteContent(const ContentData& data); X_RESULT DeleteContent(const ContentData& data);
std::filesystem::path ResolveGameUserContentPath(); std::filesystem::path ResolveGameUserContentPath();
bool IsContentOpen(const ContentData& data) const;
private: private:
std::filesystem::path ResolvePackageRoot(uint32_t content_type); std::filesystem::path ResolvePackageRoot(uint32_t content_type);