mirror of
https://github.com/boostorg/filesystem.git
synced 2025-05-12 13:41:47 +00:00
Merge pull request #102 from stima/develop
Correct handling status of reparse point
This commit is contained in:
commit
a916a41602
@ -1987,6 +1987,8 @@ file_status status(const path& p, error_code* ec)
|
|||||||
return process_status_failure(p, ec);
|
return process_status_failure(p, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ec != 0) ec->clear();
|
||||||
|
|
||||||
perms permissions = make_permissions(p, attr);
|
perms permissions = make_permissions(p, attr);
|
||||||
|
|
||||||
// reparse point handling;
|
// reparse point handling;
|
||||||
@ -1994,6 +1996,12 @@ file_status status(const path& p, error_code* ec)
|
|||||||
// handle to discover if the file exists
|
// handle to discover if the file exists
|
||||||
if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
|
if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
{
|
{
|
||||||
|
if (!is_reparse_point_a_symlink(p))
|
||||||
|
{
|
||||||
|
return file_status(reparse_file, permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to resolve symlink
|
||||||
handle_wrapper h(
|
handle_wrapper h(
|
||||||
create_file_handle(
|
create_file_handle(
|
||||||
p.c_str(),
|
p.c_str(),
|
||||||
@ -2003,16 +2011,22 @@ file_status status(const path& p, error_code* ec)
|
|||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_FLAG_BACKUP_SEMANTICS,
|
FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
0)); // hTemplateFile
|
0)); // hTemplateFile
|
||||||
|
|
||||||
if (h.handle == INVALID_HANDLE_VALUE)
|
if (h.handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
return process_status_failure(p, ec);
|
return process_status_failure(p, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_reparse_point_a_symlink(p))
|
// take attributes of target
|
||||||
return file_status(reparse_file, permissions);
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
|
if (!::GetFileInformationByHandle(h.handle, &info))
|
||||||
|
{
|
||||||
|
return process_status_failure(p, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
attr = info.dwFileAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ec != 0) ec->clear();
|
|
||||||
return (attr & FILE_ATTRIBUTE_DIRECTORY)
|
return (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
? file_status(directory_file, permissions)
|
? file_status(directory_file, permissions)
|
||||||
: file_status(regular_file, permissions);
|
: file_status(regular_file, permissions);
|
||||||
|
@ -78,3 +78,4 @@ run quick.cpp ;
|
|||||||
run issues/70-71-copy.cpp ;
|
run issues/70-71-copy.cpp ;
|
||||||
|
|
||||||
run issues/99_canonical_with_junction_point.cpp : : : <conditional>@check-mklink ;
|
run issues/99_canonical_with_junction_point.cpp : : : <conditional>@check-mklink ;
|
||||||
|
run issues/reparce_tag_file_placeholder.cpp : : : <conditional>@check-mklink ;
|
||||||
|
142
test/issues/reparce_tag_file_placeholder.cpp
Normal file
142
test/issues/reparce_tag_file_placeholder.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// Boost operations_test.cpp ---------------------------------------------------------//
|
||||||
|
|
||||||
|
// Copyright Roman Savchenko 2020
|
||||||
|
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// See http://www.boost.org/LICENSE_1_0.txt
|
||||||
|
|
||||||
|
// Library home page: http://www.boost.org/libs/filesystem
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/core/lightweight_test.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
# include <windows.h>
|
||||||
|
# include <winnt.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma comment(lib, "Advapi32.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Test correct boost::filesystem::status when reparse point ReparseTag set to IO_REPARSE_TAG_FILE_PLACEHOLDER
|
||||||
|
// https://docs.microsoft.com/en-us/windows/compatibility/placeholder-files?redirectedfrom=MSDN
|
||||||
|
|
||||||
|
#if !defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
|
typedef struct _REPARSE_DATA_BUFFER {
|
||||||
|
ULONG ReparseTag;
|
||||||
|
USHORT ReparseDataLength;
|
||||||
|
USHORT Reserved;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
USHORT SubstituteNameOffset;
|
||||||
|
USHORT SubstituteNameLength;
|
||||||
|
USHORT PrintNameOffset;
|
||||||
|
USHORT PrintNameLength;
|
||||||
|
ULONG Flags;
|
||||||
|
WCHAR PathBuffer[1];
|
||||||
|
} SymbolicLinkReparseBuffer;
|
||||||
|
struct {
|
||||||
|
USHORT SubstituteNameOffset;
|
||||||
|
USHORT SubstituteNameLength;
|
||||||
|
USHORT PrintNameOffset;
|
||||||
|
USHORT PrintNameLength;
|
||||||
|
WCHAR PathBuffer[1];
|
||||||
|
} MountPointReparseBuffer;
|
||||||
|
struct {
|
||||||
|
UCHAR DataBuffer[1];
|
||||||
|
} GenericReparseBuffer;
|
||||||
|
};
|
||||||
|
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IO_REPARSE_TAG_FILE_PLACEHOLDER
|
||||||
|
# define IO_REPARSE_TAG_FILE_PLACEHOLDER (0x80000015L)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FSCTL_SET_REPARSE_POINT
|
||||||
|
# define FSCTL_SET_REPARSE_POINT (0x000900a4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
|
||||||
|
# define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool obtain_restore_privilege()
|
||||||
|
{
|
||||||
|
HANDLE hToken;
|
||||||
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
|
||||||
|
{
|
||||||
|
std::cout << "OpenProcessToken() failed with: " << GetLastError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOKEN_PRIVILEGES tp;
|
||||||
|
if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
|
||||||
|
{
|
||||||
|
CloseHandle(hToken);
|
||||||
|
std::cout << "LookupPrivilegeValue() failed with: " << GetLastError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tp.PrivilegeCount = 1;
|
||||||
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
|
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
|
||||||
|
{
|
||||||
|
CloseHandle(hToken);
|
||||||
|
std::cout << "AdjustTokenPrivileges() failed with: " << GetLastError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool create_io_reparse_file_placeholder(const wchar_t* name)
|
||||||
|
{
|
||||||
|
if (!obtain_restore_privilege())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hHandle = CreateFileW(name, GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
|
||||||
|
FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||||
|
|
||||||
|
if (hHandle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
std::cout << "CreateFile() failed with: " << GetLastError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PREPARSE_DATA_BUFFER pReparse = reinterpret_cast<PREPARSE_DATA_BUFFER>(GlobalAlloc(GPTR, MAXIMUM_REPARSE_DATA_BUFFER_SIZE));
|
||||||
|
//note: IO_REPARSE_TAG_FILE_PLACEHOLDER - just to show that reparse point could be not only symlink or junction
|
||||||
|
pReparse->ReparseTag = IO_REPARSE_TAG_FILE_PLACEHOLDER;
|
||||||
|
|
||||||
|
DWORD dwLen;
|
||||||
|
bool ret = DeviceIoControl(hHandle, FSCTL_SET_REPARSE_POINT, pReparse,
|
||||||
|
pReparse->ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE,
|
||||||
|
NULL, 0, &dwLen, NULL) != 0;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
std::cout << "DeviceIoControl() failed with: " << GetLastError() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hHandle);
|
||||||
|
GlobalFree(pReparse);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
boost::filesystem::path rpt = boost::filesystem::temp_directory_path() / "reparse_point_test.txt";
|
||||||
|
|
||||||
|
BOOST_TEST(create_io_reparse_file_placeholder(rpt.native().c_str()));
|
||||||
|
BOOST_TEST(boost::filesystem::status(rpt).type() == boost::filesystem::reparse_file);
|
||||||
|
BOOST_TEST(boost::filesystem::remove(rpt));
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user