mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 01:27:00 +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
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
||||
if (!GetFileAttributesExW(to_wchar(path).get(), GetFileExInfoStandard, &attrs))
|
||||
WIN32_FIND_DATA 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());
|
||||
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_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.mtime = to_time(attrs.ftLastWriteTime);
|
||||
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)
|
||||
{
|
||||
if (auto device = get_virtual_device(path))
|
||||
{
|
||||
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
|
||||
fs::stat_t info{};
|
||||
return fs::stat(path, info);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#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
|
||||
#ifdef _WIN32
|
||||
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
#else
|
||||
if (S_ISDIR(file_info.st_mode))
|
||||
#endif
|
||||
if (info.is_directory)
|
||||
{
|
||||
g_tls_error = error::exist;
|
||||
return false;
|
||||
@ -466,44 +453,13 @@ bool fs::is_file(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;
|
||||
}
|
||||
#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 ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
#else
|
||||
if (!S_ISDIR(file_info.st_mode))
|
||||
#endif
|
||||
if (!info.is_directory)
|
||||
{
|
||||
g_tls_error = error::exist;
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user