[VFS/Posix] Fix Rename to properly handle guest paths
And ensure string_views aren't pointing at freed memory by saving a reference to the result of path_to_utf8
This commit is contained in:
committed by
Radosław Gliński
parent
dce4d38c0a
commit
4b6ac45650
@@ -14,6 +14,7 @@
|
||||
#include "xenia/base/mapped_memory.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/string.h"
|
||||
#include "xenia/base/utf8.h"
|
||||
#include "xenia/vfs/device.h"
|
||||
#include "xenia/vfs/devices/host_path_device.h"
|
||||
#include "xenia/vfs/devices/host_path_file.h"
|
||||
@@ -121,12 +122,20 @@ bool HostPathEntry::DeleteEntryInternal(Entry* entry) {
|
||||
}
|
||||
}
|
||||
|
||||
void HostPathEntry::RenameEntryInternal(const std::filesystem::path file_path) {
|
||||
void HostPathEntry::RenameEntryInternal(
|
||||
const std::vector<std::string_view>& path_parts) {
|
||||
const std::string relative_path = xe::utf8::join_paths(path_parts);
|
||||
const std::string new_host_path_ = xe::utf8::join_paths(
|
||||
xe::path_to_utf8(((HostPathDevice*)device_)->host_path()),
|
||||
xe::path_to_utf8(file_path));
|
||||
xe::path_to_utf8(static_cast<HostPathDevice*>(device_)->host_path()),
|
||||
relative_path);
|
||||
|
||||
std::filesystem::rename(host_path_, new_host_path_);
|
||||
std::error_code ec;
|
||||
std::filesystem::rename(host_path_, new_host_path_, ec);
|
||||
if (ec) {
|
||||
XELOGE("RenameEntryInternal: Failed to rename '{}' to '{}': {}",
|
||||
xe::path_to_utf8(host_path_), new_host_path_, ec.message());
|
||||
return;
|
||||
}
|
||||
host_path_ = new_host_path_;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ class HostPathEntry : public Entry {
|
||||
std::unique_ptr<Entry> CreateEntryInternal(const std::string_view name,
|
||||
uint32_t attributes) override;
|
||||
bool DeleteEntryInternal(Entry* entry) override;
|
||||
void RenameEntryInternal(const std::filesystem::path file_path) override;
|
||||
void RenameEntryInternal(
|
||||
const std::vector<std::string_view>& path_parts) override;
|
||||
|
||||
std::filesystem::path host_path_;
|
||||
};
|
||||
|
||||
@@ -135,19 +135,19 @@ void Entry::Touch() {
|
||||
}
|
||||
|
||||
void Entry::Rename(const std::filesystem::path file_path) {
|
||||
std::vector<std::string_view> splitted_path =
|
||||
xe::utf8::split_path(xe::path_to_utf8(file_path));
|
||||
// Store the string to ensure string_views from split_path remain valid
|
||||
const std::string path_str = xe::path_to_utf8(file_path);
|
||||
std::vector<std::string_view> path_parts = xe::utf8::split_path(path_str);
|
||||
|
||||
splitted_path.erase(splitted_path.begin());
|
||||
// Remove the root (e.g., "cache:")
|
||||
path_parts.erase(path_parts.begin());
|
||||
|
||||
const std::string guest_path_without_root =
|
||||
xe::utf8::join_guest_paths(splitted_path);
|
||||
RenameEntryInternal(path_parts);
|
||||
|
||||
RenameEntryInternal(guest_path_without_root);
|
||||
|
||||
absolute_path_ = xe::utf8::join_guest_paths(device_->mount_path(),
|
||||
guest_path_without_root);
|
||||
path_ = guest_path_without_root;
|
||||
const std::string guest_path = xe::utf8::join_guest_paths(path_parts);
|
||||
absolute_path_ =
|
||||
xe::utf8::join_guest_paths(device_->mount_path(), guest_path);
|
||||
path_ = guest_path;
|
||||
name_ = xe::path_to_utf8(file_path.filename());
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,8 @@ class Entry {
|
||||
return nullptr;
|
||||
}
|
||||
virtual bool DeleteEntryInternal(Entry* entry) = 0;
|
||||
virtual void RenameEntryInternal(const std::filesystem::path file_path) {}
|
||||
virtual void RenameEntryInternal(
|
||||
const std::vector<std::string_view>& path_parts) {}
|
||||
|
||||
xe::global_critical_region global_critical_region_;
|
||||
Device* device_;
|
||||
|
||||
Reference in New Issue
Block a user