Skip to content

Commit

Permalink
Improve vfs::host::unlink on Windows (for sys_fs_rmdir)
Browse files Browse the repository at this point in the history
Possibly fixes sys_fs_rmdir and other cases of directory removal.
Make sure the directory with deleted files always becomes empty.
For this purpose, temp files are moved to the root of the device.
  • Loading branch information
Nekotekina committed Sep 25, 2019
1 parent cd843bd commit ccf9543
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 5 deletions.
9 changes: 7 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_fs.cpp
Expand Up @@ -862,7 +862,9 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
const std::string_view vpath = path.get_ptr();
const std::string local_path = vfs::get(vpath);

if (vpath.find_first_not_of('/') == -1)
const std::size_t dev_start = vpath.find_first_not_of('/');

if (dev_start == -1)
{
return {CELL_EISDIR, path};
}
Expand All @@ -877,7 +879,10 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
return {CELL_EISDIR, path};
}

if (!vfs::host::unlink(local_path))
// Size of "/dev_hdd0"-alike substring
const std::size_t dev_size = vpath.find_first_of('/', dev_start);

if (!vfs::host::unlink(local_path, vfs::get(vpath.substr(0, dev_size))))
{
switch (auto error = fs::g_tls_error)
{
Expand Down
6 changes: 4 additions & 2 deletions rpcs3/Emu/VFS.cpp
Expand Up @@ -33,6 +33,8 @@ bool vfs::mount(std::string_view vpath, std::string_view path)

const auto table = g_fxo->get<vfs_manager>();

// TODO: scan roots of mounted devices for undeleted vfs::host::unlink remnants, and try to delete them (_WIN32 only)

std::lock_guard lock(table->mutex);

if (vpath.empty())
Expand Down Expand Up @@ -566,13 +568,13 @@ bool vfs::host::rename(const std::string& from, const std::string& to, bool over
return true;
}

bool vfs::host::unlink(const std::string& path)
bool vfs::host::unlink(const std::string& path, const std::string& dev_root)
{
#ifdef _WIN32
if (path.size() < 2 || reinterpret_cast<const u16&>(path.front()) != "//"_u16)
{
// Rename to special dummy name which will be ignored by VFS (but opened file handles can still read or write it)
const std::string dummy = fmt::format(u8"%s/$%s%s", fs::get_parent_dir(path), fmt::base57(std::hash<std::string>()(path)), fmt::base57(__rdtsc()));
const std::string dummy = fmt::format(u8"%s/$%s%s", dev_root, fmt::base57(std::hash<std::string>()(path)), fmt::base57(__rdtsc()));

if (!fs::rename(path, dummy, true))
{
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/VFS.h
Expand Up @@ -25,6 +25,6 @@ namespace vfs
bool rename(const std::string& from, const std::string& to, bool overwrite);

// Delete file without deleting its contents, emulated with MoveFileEx on Windows
bool unlink(const std::string&);
bool unlink(const std::string& path, const std::string& dev_root);
}
}

0 comments on commit ccf9543

Please sign in to comment.