mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
Win32 FS: Use FindFirstFileExW in fs::stat, fs::exists, fs::is_dir, fs::is_file
Co-Authored-By: Bevan Weiss <bevanweiss@users.noreply.github.com>
This commit is contained in:
parent
da6760ed98
commit
8c8048f037
@ -352,16 +352,57 @@ bool fs::stat(const std::string& path, stat_t& info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
WIN32_FIND_DATA attrs;
|
||||||
if (!GetFileAttributesExW(to_wchar(path).get(), GetFileExInfoStandard, &attrs))
|
std::string_view epath = path;
|
||||||
|
|
||||||
|
// '/' and '\\' Not allowed by FindFirstFileExW at the end of path but we should allow it
|
||||||
|
if (auto not_del = epath.find_last_not_of("/\\"); not_del != umax && not_del != epath.size() - 1)
|
||||||
|
{
|
||||||
|
epath.remove_suffix(path.size() - 1 - not_del);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allowed by FindFirstFileExW but we should not allow it
|
||||||
|
if (epath.ends_with("*"))
|
||||||
|
{
|
||||||
|
g_tls_error = fs::error::noent;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto wchar_ptr = to_wchar(std::string(epath));
|
||||||
|
const std::wstring_view wpath_view = wchar_ptr.get();
|
||||||
|
|
||||||
|
const HANDLE handle = FindFirstFileExW(wpath_view.data(), FindExInfoStandard, &attrs, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_CASE_SENSITIVE);
|
||||||
|
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
g_tls_error = to_error(GetLastError());
|
g_tls_error = to_error(GetLastError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct close_t
|
||||||
|
{
|
||||||
|
HANDLE handle;
|
||||||
|
~close_t() { FindClose(handle); }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (close_t find_manage{handle}; attrs.cFileName != wpath_view.substr(wpath_view.find_last_of(L"/\\") + 1);)
|
||||||
|
{
|
||||||
|
if (!FindNextFileW(handle, &attrs))
|
||||||
|
{
|
||||||
|
if (const DWORD err = GetLastError(); err != ERROR_NO_MORE_FILES)
|
||||||
|
{
|
||||||
|
g_tls_error = to_error(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_tls_error = fs::error::noent;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
info.is_directory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
info.is_directory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||||
info.is_writable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
|
info.is_writable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
|
||||||
info.size = (u64)attrs.nFileSizeLow | ((u64)attrs.nFileSizeHigh << 32);
|
info.size = attrs.nFileSizeLow | (u64{attrs.nFileSizeHigh} << 32);
|
||||||
info.atime = to_time(attrs.ftLastAccessTime);
|
info.atime = to_time(attrs.ftLastAccessTime);
|
||||||
info.mtime = to_time(attrs.ftLastWriteTime);
|
info.mtime = to_time(attrs.ftLastWriteTime);
|
||||||
info.ctime = info.mtime;
|
info.ctime = info.mtime;
|
||||||
@ -389,73 +430,19 @@ bool fs::stat(const std::string& path, stat_t& info)
|
|||||||
|
|
||||||
bool fs::exists(const std::string& path)
|
bool fs::exists(const std::string& path)
|
||||||
{
|
{
|
||||||
if (auto device = get_virtual_device(path))
|
fs::stat_t info{};
|
||||||
{
|
return fs::stat(path, info);
|
||||||
stat_t info;
|
|
||||||
return device->stat(path, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (GetFileAttributesW(to_wchar(path).get()) == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
|
||||||
g_tls_error = to_error(GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
struct ::stat file_info;
|
|
||||||
if (::stat(path.c_str(), &file_info) != 0)
|
|
||||||
{
|
|
||||||
g_tls_error = to_error(errno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs::is_file(const std::string& path)
|
bool fs::is_file(const std::string& path)
|
||||||
{
|
{
|
||||||
if (auto device = get_virtual_device(path))
|
fs::stat_t info{};
|
||||||
|
if (!fs::stat(path, info))
|
||||||
{
|
{
|
||||||
stat_t info;
|
|
||||||
if (!device->stat(path, info))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.is_directory)
|
|
||||||
{
|
|
||||||
g_tls_error = error::exist;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
|
|
||||||
if (attrs == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
|
||||||
g_tls_error = to_error(GetLastError());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
struct ::stat file_info;
|
|
||||||
if (::stat(path.c_str(), &file_info) != 0)
|
|
||||||
{
|
|
||||||
g_tls_error = to_error(errno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: correct file type check
|
if (info.is_directory)
|
||||||
#ifdef _WIN32
|
|
||||||
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
|
||||||
#else
|
|
||||||
if (S_ISDIR(file_info.st_mode))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
g_tls_error = error::exist;
|
g_tls_error = error::exist;
|
||||||
return false;
|
return false;
|
||||||
@ -466,44 +453,13 @@ bool fs::is_file(const std::string& path)
|
|||||||
|
|
||||||
bool fs::is_dir(const std::string& path)
|
bool fs::is_dir(const std::string& path)
|
||||||
{
|
{
|
||||||
if (auto device = get_virtual_device(path))
|
fs::stat_t info{};
|
||||||
|
if (!fs::stat(path, info))
|
||||||
{
|
{
|
||||||
stat_t info;
|
|
||||||
if (!device->stat(path, info))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.is_directory == false)
|
|
||||||
{
|
|
||||||
g_tls_error = error::exist;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
|
|
||||||
if (attrs == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
|
||||||
g_tls_error = to_error(GetLastError());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
struct ::stat file_info;
|
|
||||||
if (::stat(path.c_str(), &file_info) != 0)
|
|
||||||
{
|
|
||||||
g_tls_error = to_error(errno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
if (!info.is_directory)
|
||||||
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
|
||||||
#else
|
|
||||||
if (!S_ISDIR(file_info.st_mode))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
g_tls_error = error::exist;
|
g_tls_error = error::exist;
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user