aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/filesystem.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-09-12 08:03:46 -0400
committerGitHub <[email protected]>2023-09-12 14:03:46 +0200
commitf463686b9621b8c744e2dcb0d018ad507716d499 (patch)
tree7cf50625dbfe3b731131b779c6286ae9ca6423d7 /src/zencore/filesystem.cpp
parentgracefully handle errors when writing cache log (#391) (diff)
downloadzen-f463686b9621b8c744e2dcb0d018ad507716d499.tar.xz
zen-f463686b9621b8c744e2dcb0d018ad507716d499.zip
Make sure error logging or destructors don't throw exception when trying to get file name from handle (#393)
- Bugfix: Make sure error logging or destructors don't throw exception when trying to get file name from handle
Diffstat (limited to 'src/zencore/filesystem.cpp')
-rw-r--r--src/zencore/filesystem.cpp57
1 files changed, 44 insertions, 13 deletions
diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp
index 8abe5af00..b1ec14a37 100644
--- a/src/zencore/filesystem.cpp
+++ b/src/zencore/filesystem.cpp
@@ -1063,19 +1063,25 @@ FileSystemTraversal::TraverseFileSystem(const std::filesystem::path& RootDir, Tr
closedir(Dir);
#endif // ZEN_PLATFORM_WINDOWS
}
-
std::filesystem::path
-PathFromHandle(void* NativeHandle)
+PathFromHandle(void* NativeHandle, std::error_code& Ec)
{
+ if (NativeHandle == nullptr)
+ {
+ return std::filesystem::path();
+ }
#if ZEN_PLATFORM_WINDOWS
- if (NativeHandle == nullptr || NativeHandle == INVALID_HANDLE_VALUE)
+ if (NativeHandle == INVALID_HANDLE_VALUE)
{
return std::filesystem::path();
}
- auto GetFinalPathNameByHandleWRetry = [](HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags) -> DWORD {
- while (true)
+ auto GetFinalPathNameByHandleWRetry =
+ [&Ec](HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags, DWORD& OutRequiredLength) -> DWORD {
+ size_t MaxTries = 5;
+ while (MaxTries > 0)
{
+ MaxTries--;
DWORD Res = GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags);
if (Res == 0)
{
@@ -1084,22 +1090,27 @@ PathFromHandle(void* NativeHandle)
// Retry if that is the case.
if (LastError != ERROR_ACCESS_DENIED)
{
- ThrowSystemError(LastError, fmt::format("failed to get path from file handle {}", hFile));
+ Sleep(2);
+ return LastError;
}
// Retry
continue;
}
ZEN_ASSERT(Res != 1); // We don't accept empty path names
- return Res;
+ OutRequiredLength = Res;
+ return ERROR_SUCCESS;
}
+ return ERROR_ACCESS_DENIED;
};
static const DWORD PathDataSize = 512;
wchar_t PathData[PathDataSize];
- DWORD RequiredLengthIncludingNul = GetFinalPathNameByHandleWRetry(NativeHandle, PathData, PathDataSize, FILE_NAME_OPENED);
- if (RequiredLengthIncludingNul == 0)
+ DWORD RequiredLengthIncludingNul = 0;
+ DWORD Error = GetFinalPathNameByHandleWRetry(NativeHandle, PathData, PathDataSize, FILE_NAME_OPENED, RequiredLengthIncludingNul);
+ if (Error != ERROR_SUCCESS)
{
- ThrowLastError(fmt::format("failed to get path from file handle {}", NativeHandle));
+ Ec = MakeErrorCodeFromLastError();
+ return std::filesystem::path();
}
if (RequiredLengthIncludingNul < PathDataSize)
@@ -1111,7 +1122,13 @@ PathFromHandle(void* NativeHandle)
std::wstring FullPath;
FullPath.resize(RequiredLengthIncludingNul - 1);
- const DWORD FinalLength = GetFinalPathNameByHandleWRetry(NativeHandle, FullPath.data(), RequiredLengthIncludingNul, FILE_NAME_OPENED);
+ DWORD FinalLength = 0;
+ Error = GetFinalPathNameByHandleWRetry(NativeHandle, FullPath.data(), RequiredLengthIncludingNul, FILE_NAME_OPENED, FinalLength);
+ if (Error != ERROR_SUCCESS)
+ {
+ Ec = MakeErrorCodeFromLastError();
+ return std::filesystem::path();
+ }
ZEN_UNUSED(FinalLength);
return FullPath;
@@ -1123,7 +1140,8 @@ PathFromHandle(void* NativeHandle)
ssize_t BytesRead = readlink(Path, Link, sizeof(Link) - 1);
if (BytesRead <= 0)
{
- return std::filesystem::path();
+ Ec = MakeErrorCodeFromLastError();
+ return {};
}
Link[BytesRead] = '\0';
@@ -1133,13 +1151,26 @@ PathFromHandle(void* NativeHandle)
char Path[MAXPATHLEN];
if (fcntl(Fd, F_GETPATH, Path) < 0)
{
- return std::filesystem::path();
+ Ec = MakeErrorCodeFromLastError();
+ return {};
}
return Path;
#endif // ZEN_PLATFORM_WINDOWS
}
+std::filesystem::path
+PathFromHandle(void* NativeHandle)
+{
+ std::error_code Ec;
+ std::filesystem::path Result = PathFromHandle(NativeHandle, Ec);
+ if (Ec)
+ {
+ throw std::system_error(Ec, fmt::format("failed to get path from file handle '{}'", NativeHandle));
+ }
+ return Result;
+}
+
uint64_t
FileSizeFromHandle(void* NativeHandle)
{