From ef373416f30080dbe9b714f24e552a0015ff77f9 Mon Sep 17 00:00:00 2001 From: Tobias Kloss <tobias.kloss@draeger.com> Date: Fri, 18 Jan 2019 08:04:58 -0500 Subject: [PATCH] SystemTools: Fix FileIsSymlink with Windows data deduplication On Windows machines with enabled data deduplication files duplicates are incorrectly recognized as symlinks and therefore install fails with "file COPY cannot read symlink". Similar issues can be found here: * https://github.com/Microsoft/vcpkg/issues/2488 * https://github.com/puppetlabs/puppet/pull/6513 From the later fix this commit is mainly influenced. --- SystemTools.cxx | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/SystemTools.cxx b/SystemTools.cxx index c5160a9..e78d95e 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -2982,7 +2982,28 @@ bool SystemTools::FileIsSymlink(const std::string& name) DWORD attr = GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str()); if (attr != INVALID_FILE_ATTRIBUTES) { - return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0; + if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { + HANDLE hFile = CreateFileW(Encoding::ToWide(name).c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + DWORD bytesReturned = 0; + if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, + NULL)) { + CloseHandle(hFile); + return false; + } + CloseHandle(hFile); + ULONG reparseTag = + reinterpret_cast<PREPARSE_GUID_DATA_BUFFER>(&buffer[0])->ReparseTag; + return (reparseTag == IO_REPARSE_TAG_SYMLINK) || + (reparseTag == IO_REPARSE_TAG_MOUNT_POINT); + } + return false; } else { return false; } -- GitLab