Skip to content

Commit 4f2e707

Browse files
committed
[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
1 parent dce4d38 commit 4f2e707

File tree

4 files changed

+26
-16
lines changed

4 files changed

+26
-16
lines changed

src/xenia/vfs/devices/host_path_entry.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "xenia/base/mapped_memory.h"
1515
#include "xenia/base/math.h"
1616
#include "xenia/base/string.h"
17+
#include "xenia/base/utf8.h"
1718
#include "xenia/vfs/device.h"
1819
#include "xenia/vfs/devices/host_path_device.h"
1920
#include "xenia/vfs/devices/host_path_file.h"
@@ -121,12 +122,19 @@ bool HostPathEntry::DeleteEntryInternal(Entry* entry) {
121122
}
122123
}
123124

124-
void HostPathEntry::RenameEntryInternal(const std::filesystem::path file_path) {
125+
void HostPathEntry::RenameEntryInternal(
126+
const std::vector<std::string_view>& path_parts) {
127+
const std::string relative_path = xe::utf8::join_paths(path_parts);
125128
const std::string new_host_path_ = xe::utf8::join_paths(
126-
xe::path_to_utf8(((HostPathDevice*)device_)->host_path()),
127-
xe::path_to_utf8(file_path));
129+
xe::path_to_utf8(((HostPathDevice*)device_)->host_path()), relative_path);
128130

129-
std::filesystem::rename(host_path_, new_host_path_);
131+
std::error_code ec;
132+
std::filesystem::rename(host_path_, new_host_path_, ec);
133+
if (ec) {
134+
XELOGE("RenameEntryInternal: Failed to rename '{}' to '{}': {}",
135+
xe::path_to_utf8(host_path_), new_host_path_, ec.message());
136+
return;
137+
}
130138
host_path_ = new_host_path_;
131139
}
132140

src/xenia/vfs/devices/host_path_entry.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ class HostPathEntry : public Entry {
5151
std::unique_ptr<Entry> CreateEntryInternal(const std::string_view name,
5252
uint32_t attributes) override;
5353
bool DeleteEntryInternal(Entry* entry) override;
54-
void RenameEntryInternal(const std::filesystem::path file_path) override;
54+
void RenameEntryInternal(
55+
const std::vector<std::string_view>& path_parts) override;
5556

5657
std::filesystem::path host_path_;
5758
};

src/xenia/vfs/entry.cc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,19 +135,19 @@ void Entry::Touch() {
135135
}
136136

137137
void Entry::Rename(const std::filesystem::path file_path) {
138-
std::vector<std::string_view> splitted_path =
139-
xe::utf8::split_path(xe::path_to_utf8(file_path));
138+
// Store the string to ensure string_views from split_path remain valid
139+
const std::string path_str = xe::path_to_utf8(file_path);
140+
std::vector<std::string_view> path_parts = xe::utf8::split_path(path_str);
140141

141-
splitted_path.erase(splitted_path.begin());
142+
// Remove the root (e.g., "cache:")
143+
path_parts.erase(path_parts.begin());
142144

143-
const std::string guest_path_without_root =
144-
xe::utf8::join_guest_paths(splitted_path);
145+
RenameEntryInternal(path_parts);
145146

146-
RenameEntryInternal(guest_path_without_root);
147-
148-
absolute_path_ = xe::utf8::join_guest_paths(device_->mount_path(),
149-
guest_path_without_root);
150-
path_ = guest_path_without_root;
147+
const std::string guest_path = xe::utf8::join_guest_paths(path_parts);
148+
absolute_path_ =
149+
xe::utf8::join_guest_paths(device_->mount_path(), guest_path);
150+
path_ = guest_path;
151151
name_ = xe::path_to_utf8(file_path.filename());
152152
}
153153

src/xenia/vfs/entry.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ class Entry {
141141
return nullptr;
142142
}
143143
virtual bool DeleteEntryInternal(Entry* entry) = 0;
144-
virtual void RenameEntryInternal(const std::filesystem::path file_path) {}
144+
virtual void RenameEntryInternal(
145+
const std::vector<std::string_view>& path_parts) {}
145146

146147
xe::global_critical_region global_critical_region_;
147148
Device* device_;

0 commit comments

Comments
 (0)