Skip to content

Commit

Permalink
Filesystem/Win32: Recreate hardlinks on fs::pending_file
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Oct 27, 2024
1 parent e2f9548 commit a3ff474
Showing 1 changed file with 47 additions and 2 deletions.
49 changes: 47 additions & 2 deletions Utilities/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2475,7 +2475,6 @@ bool fs::pending_file::commit(bool overwrite)
{
file.sync();
}

#endif

#ifdef _WIN32
Expand All @@ -2486,16 +2485,62 @@ bool fs::pending_file::commit(bool overwrite)
disp.DeleteFileW = false;
ensure(SetFileInformationByHandle(file.get_handle(), FileDispositionInfo, &disp, sizeof(disp)));
}

std::vector<std::wstring> hardlinkPaths;

const auto ws1 = to_wchar(m_path);

const HANDLE fileHandle = CreateFileW(ws1.get(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);

while (fileHandle != INVALID_HANDLE_VALUE)
{
// Get file ID (used to check for hardlinks)
BY_HANDLE_FILE_INFORMATION fileInfo;

if (!GetFileInformationByHandle(fileHandle, &fileInfo) || fileInfo.nNumberOfLinks == 1)
{
CloseHandle(fileHandle);
break;
}

// Buffer for holding link name
WCHAR linkNameBuffer[MAX_PATH];
HANDLE findHandle = FindFirstFileNameW(ws1.get(), 0, nullptr, linkNameBuffer);

if (findHandle != INVALID_HANDLE_VALUE)
{
const std::wstring_view ws1_sv = ws1.get();

do
{
if (linkNameBuffer != ws1_sv)
{
hardlinkPaths.push_back(linkNameBuffer);
}
}
while (FindNextFileNameW(findHandle, nullptr, linkNameBuffer));
}

// Clean up
FindClose(findHandle);
CloseHandle(fileHandle);
break;
}
#endif

file.close();

#ifdef _WIN32
const auto ws1 = to_wchar(m_path);
const auto ws2 = to_wchar(m_dest);

if (MoveFileExW(ws1.get(), ws2.get(), overwrite ? MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH : MOVEFILE_WRITE_THROUGH))
{
for (auto&& path : hardlinkPaths)
{
// Recreate hard links
createHardLinkW(m_dest.c_str(), path.c_str());
}

// Disable the destructor
m_path.clear();
return true;
Expand Down

0 comments on commit a3ff474

Please sign in to comment.