Skip to content

Instantly share code, notes, and snippets.

@BillyONeal
Created February 21, 2017 05:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save BillyONeal/7209d5d118a301ffec86fb195222d62a to your computer and use it in GitHub Desktop.
Save BillyONeal/7209d5d118a301ffec86fb195222d62a to your computer and use it in GitHub Desktop.
std::filesystem::equivalent
#include <vcruntime.h>
__std_win32_error __std_fs_equivalent(bool * _Result, const wchar_t *_Path1, const wchar_t *_Path2) noexcept
{ // test for equivalent file names
const __vcp_unique_handle _Handle1(_FilesysOpenFile(_Path1, FILE_READ_ATTRIBUTES,
FILE_FLAG_BACKUP_SEMANTICS));
if (!_Handle1.is_valid())
{
*_Result = false;
return (GetLastError());
}
const __vcp_unique_handle _Handle2(_FilesysOpenFile(_Path2, FILE_READ_ATTRIBUTES,
FILE_FLAG_BACKUP_SEMANTICS));
if (!_Handle2.is_valid())
{
*_Result = false;
return (GetLastError());
}
if (__vcp_has_GetFileInformationByHandleEx())
{
_FILE_ID_INFO _Info1;
if (__vcp_GetFileInformationByHandleEx(_Handle1.get(), FileIdInfo, &_Info1, sizeof(_Info1)) == 0)
{
DWORD _LastError = GetLastError();
if (_LastError == ERROR_INVALID_PARAMETER)
{ // Windows Vista through Windows 7 don't support FileIdInfo
goto tryGetFileInformationByHandle;
}
*_Result = false;
return (_LastError);
}
_FILE_ID_INFO _Info2;
if (__vcp_GetFileInformationByHandleEx(_Handle2.get(), FileIdInfo, &_Info2, sizeof(_Info2)) == 0)
{
*_Result = false;
return (GetLastError());
}
static_assert(sizeof(_Info1) == sizeof(_Info1.VolumeSerialNumber) + sizeof(_Info1.FileId),
"cannot combine comparisons");
*_Result = memcmp(&_Info1, &_Info2, sizeof(_Info1)) == 0;
return (__std_win32_success);
}
tryGetFileInformationByHandle:
if (__vcp_has_GetFileInformationByHandle())
{
BY_HANDLE_FILE_INFORMATION _Info1;
if (__vcp_GetFileInformationByHandle(_Handle1.get(), &_Info1) == 0)
{
*_Result = false;
return (GetLastError());
}
BY_HANDLE_FILE_INFORMATION _Info2;
if (__vcp_GetFileInformationByHandle(_Handle2.get(), &_Info2) == 0)
{
*_Result = false;
return (GetLastError());
}
*_Result = _Info1.dwVolumeSerialNumber == _Info2.dwVolumeSerialNumber
&& _Info1.nFileIndexHigh == _Info2.nFileIndexHigh
&& _Info1.nFileIndexLow == _Info2.nFileIndexLow;
return (__std_win32_success);
}
return (ERROR_NOT_SUPPORTED);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment