Skip to content

Commit

Permalink
Win32 FS: Rewrite (fix) vfs::host::rename
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Sep 11, 2020
1 parent 9ff0b46 commit c8d6599
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 7 deletions.
7 changes: 5 additions & 2 deletions Utilities/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
#endif
}

bool fs::utime(const std::string& path, s64 atime, s64 mtime)
bool fs::utime(const std::string& path, s64 atime, s64 mtime, std::optional<s64> ctime)
{
if (auto device = get_virtual_device(path))
{
Expand All @@ -864,7 +864,8 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)

FILETIME _atime = from_time(atime);
FILETIME _mtime = from_time(mtime);
if (!SetFileTime(handle, nullptr, &_atime, &_mtime))
FILETIME _ctime = from_time(ctime.value_or(0));
if (!SetFileTime(handle, ctime ? &_ctime : nullptr, &_atime, &_mtime))
{
g_tls_error = to_error(GetLastError());
CloseHandle(handle);
Expand All @@ -874,6 +875,8 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)
CloseHandle(handle);
return true;
#else
verify(HERE), !ctime.has_value();

::utimbuf buf;
buf.actime = atime;
buf.modtime = mtime;
Expand Down
3 changes: 2 additions & 1 deletion Utilities/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <memory>
#include <string>
#include <vector>
#include <optional>
#include <algorithm>


Expand Down Expand Up @@ -177,7 +178,7 @@ namespace fs
bool truncate_file(const std::string& path, u64 length);

// Set file access/modification time
bool utime(const std::string& path, s64 atime, s64 mtime);
bool utime(const std::string& path, s64 atime, s64 mtime, std::optional<s64> ctime = {});

class file final
{
Expand Down
124 changes: 120 additions & 4 deletions rpcs3/Emu/VFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "System.h"
#include "VFS.h"

#include "CPU/CPUThread.h"

#include "Utilities/mutex.h"
#include "Utilities/StrUtil.h"

Expand Down Expand Up @@ -703,16 +705,130 @@ std::string vfs::unescape(std::string_view name)

bool vfs::host::rename(const std::string& from, const std::string& to, bool overwrite)
{
while (!fs::rename(from, to, overwrite))
// Try the easy way
for (int i = 0; i < 10; i++, std::this_thread::sleep_for(5ms))
{
// Try to ignore access error in order to prevent spurious failure
if (Emu.IsStopped() || fs::g_tls_error != fs::error::acces)
if (fs::rename(from, to, overwrite))
{
return true;
}

if (fs::g_tls_error != fs::error::acces)
{
return false;
}
}

return true;
#ifdef _WIN32
// Hard way: suspend all threads execution, create dirs and move files each
cpu_thread::suspend_all cpu_lock(get_current_cpu_thread());

if (fs::is_file(from))
{
return fs::rename(from, to, overwrite);
}

if (fs::is_dir(to))
{
fs::stat_t info;

if (!fs::stat(from, info))
{
return false;
}

if (!overwrite)
{
fs::g_tls_error = fs::error::exist;
return false;
}

if (!fs::remove_dir(to))
{
return false;
}

fs::create_dir(to);

bool empty_dir = fs::remove_dir(from);

if (empty_dir)
{
fs::create_dir(from);
}

fs::utime(to, info.atime, info.mtime, info.ctime);

if (empty_dir)
{
// Protect about a case where 'to' equals 'from' and 'overwrite' is enabled
return;
}
}

std::function<bool(std::string, int)> func;

func = [&](std::string from_dir, int count) -> bool
{
const auto to_dir = to + from_dir.substr(from.size());

// Create sub-directories
if (count && !fs::create_dir(to_dir))
{
return false;
}

s64 atime, mtime, ctime;
for (const auto& item : fs::dir(from_dir))
{
if (item.name == "." || item.name == "..")
{
if (item.name == ".")
{
atime = item.atime;
mtime = item.mtime;
ctime = item.ctime;
}

continue;
}

if (item.is_directory)
{
if (!func(from_dir + '/' + item.name, count + 1))
{
return false;
}
}
else
{
const auto from_file = from_dir + '/' + item.name;
const auto to_file = to_dir + '/' + item.name;

if (!fs::rename(from_file, to_file, false))
{
return false;
}
}
}

if (!fs::remove_dir(from_dir))
{
return false;
}

if (!fs::utime(to_dir, atime, mtime, ctime))
{
return false;
}

return true;
};

return func(from, 0);
#else
return false;
#endif
}

bool vfs::host::unlink(const std::string& path, const std::string& dev_root)
Expand Down

0 comments on commit c8d6599

Please sign in to comment.