From 49584ff66494070329f44949303cd6b7d4fa9b93 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Thu, 15 Aug 2024 17:13:19 +0200 Subject: [PATCH] [VFS] Change file attributes or timestamps. Changing these options is only viable for r/w mounted host devices (Cache) Changing attributes works only on windows Changing timestamps is mocked and logged to see if there is any title that uses it --- src/xenia/base/filesystem.h | 2 + src/xenia/base/filesystem_android.cc | 4 ++ src/xenia/base/filesystem_posix.cc | 4 ++ src/xenia/base/filesystem_win.cc | 4 ++ src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc | 20 +++++++++ src/xenia/vfs/devices/host_path_entry.cc | 42 +++++++++++++++++++ src/xenia/vfs/devices/host_path_entry.h | 5 +++ src/xenia/vfs/entry.h | 5 +++ 8 files changed, 86 insertions(+) diff --git a/src/xenia/base/filesystem.h b/src/xenia/base/filesystem.h index d72cf4f3c..8ff43e669 100644 --- a/src/xenia/base/filesystem.h +++ b/src/xenia/base/filesystem.h @@ -128,6 +128,8 @@ std::vector ListDirectories(const std::filesystem::path& path); std::vector FilterByName(const std::vector& files, const std::regex pattern); +bool SetAttributes(const std::filesystem::path& path, uint64_t attributes); + #if XE_PLATFORM_ANDROID void AndroidInitialize(); void AndroidShutdown(); diff --git a/src/xenia/base/filesystem_android.cc b/src/xenia/base/filesystem_android.cc index 12f5c2d7d..3a31ad306 100644 --- a/src/xenia/base/filesystem_android.cc +++ b/src/xenia/base/filesystem_android.cc @@ -274,5 +274,9 @@ int OpenAndroidContentFileDescriptor(const std::string_view uri, return file_descriptor; } +bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) { + return false; +} + } // namespace filesystem } // namespace xe diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index eb0714663..73b06271c 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -243,5 +243,9 @@ std::vector ListFiles(const std::filesystem::path& path) { return result; } +bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) { + return false; +} + } // namespace filesystem } // namespace xe diff --git a/src/xenia/base/filesystem_win.cc b/src/xenia/base/filesystem_win.cc index 79a86d6b0..cade81ed7 100644 --- a/src/xenia/base/filesystem_win.cc +++ b/src/xenia/base/filesystem_win.cc @@ -285,5 +285,9 @@ std::vector FilterByName(const std::vector& files, return filtered_entries; } +bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) { + return SetFileAttributes(path.c_str(), static_cast(attributes)); +} + } // namespace filesystem } // namespace xe diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc index 81d1013e6..40dc70210 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc @@ -207,6 +207,26 @@ dword_result_t NtSetInformationFile_entry( switch (info_class) { case XFileBasicInformation: { auto info = info_ptr.as(); + + bool basic_result = true; + if (info->creation_time) { + basic_result &= file->entry()->SetCreateTimestamp(info->creation_time); + } + + if (info->last_access_time) { + basic_result &= + file->entry()->SetAccessTimestamp(info->last_access_time); + } + + if (info->last_write_time) { + basic_result &= file->entry()->SetWriteTimestamp(info->last_write_time); + } + + basic_result &= file->entry()->SetAttributes(info->attributes); + if (!basic_result) { + result = X_STATUS_UNSUCCESSFUL; + } + out_length = sizeof(*info); break; } diff --git a/src/xenia/vfs/devices/host_path_entry.cc b/src/xenia/vfs/devices/host_path_entry.cc index 394b445b9..dbc554fa9 100644 --- a/src/xenia/vfs/devices/host_path_entry.cc +++ b/src/xenia/vfs/devices/host_path_entry.cc @@ -132,5 +132,47 @@ void HostPathEntry::update() { } } +bool HostPathEntry::SetAttributes(uint64_t attributes) { + if (device_->is_read_only()) { + return false; + } + return xe::filesystem::SetAttributes(host_path_, attributes); +} + +bool HostPathEntry::SetCreateTimestamp(uint64_t timestamp) { + if (device_->is_read_only()) { + XELOGW( + "{} - Tried to change read-only creation timestamp for file: {} to: {}", + __FUNCTION__, name_, timestamp); + return false; + } + XELOGI("{} - Tried to change creation timestamp for file: {} to: {}", + __FUNCTION__, name_, timestamp); + return true; +} + +bool HostPathEntry::SetAccessTimestamp(uint64_t timestamp) { + if (device_->is_read_only()) { + XELOGW( + "{} - Tried to change read-only access timestamp for file: {} to: {}", + __FUNCTION__, name_, timestamp); + return false; + } + XELOGI("{} - Tried to change access timestamp for file: {} to: {}", + __FUNCTION__, name_, timestamp); + return true; +} + +bool HostPathEntry::SetWriteTimestamp(uint64_t timestamp) { + if (device_->is_read_only()) { + XELOGW("{} - Tried to change read-only write timestamp for file: {} to: {}", + __FUNCTION__, name_, timestamp); + return false; + } + XELOGI("{} - Tried to change write timestamp for file: {} to: {}", + __FUNCTION__, name_, timestamp); + return true; +} + } // namespace vfs } // namespace xe diff --git a/src/xenia/vfs/devices/host_path_entry.h b/src/xenia/vfs/devices/host_path_entry.h index c43cdde44..85ce94d8b 100644 --- a/src/xenia/vfs/devices/host_path_entry.h +++ b/src/xenia/vfs/devices/host_path_entry.h @@ -40,6 +40,11 @@ class HostPathEntry : public Entry { size_t length) override; void update() override; + bool SetAttributes(uint64_t attributes) override; + bool SetCreateTimestamp(uint64_t timestamp) override; + bool SetAccessTimestamp(uint64_t timestamp) override; + bool SetWriteTimestamp(uint64_t timestamp) override; + private: friend class HostPathDevice; diff --git a/src/xenia/vfs/entry.h b/src/xenia/vfs/entry.h index 554c696d2..9832990ff 100644 --- a/src/xenia/vfs/entry.h +++ b/src/xenia/vfs/entry.h @@ -94,6 +94,11 @@ class Entry { uint64_t access_timestamp() const { return access_timestamp_; } uint64_t write_timestamp() const { return write_timestamp_; } + virtual bool SetAttributes(uint64_t attributes) { return false; } + virtual bool SetCreateTimestamp(uint64_t timestamp) { return false; } + virtual bool SetAccessTimestamp(uint64_t timestamp) { return false; } + virtual bool SetWriteTimestamp(uint64_t timestamp) { return false; } + bool is_read_only() const; Entry* GetChild(const std::string_view name);