ned14/llfio

Windows directory junctions cannot be opened with symlink_handle

BurningEnlightenment opened this issue · 1 comments

The documentation states:

On Microsoft Windows, there are many kinds of symbolic link: this implementation supports
directory junctions, and NTFS symbolic links. Reads of any others will return an error

Which the implementation contradicts:
ntflags |= 0x040 /*FILE_NON_DIRECTORY_FILE*/; // do not open a directory

Trying to open a directory junction with the NT API path in symlink_handle::symlink() therefore always errors with the NTSTATUS 0xC00000BA STATUS_FILE_IS_A_DIRECTORY. The Win32 API path isn't affected and can be used as a workaround:

constexpr int ntstatus_file_is_a_directory = 0xC00000BA;
llfio::symlink_handle symlink;
if (auto openSymlinkRx = llfio::symlink_handle::symlink(dirh, which.leafname /*...*/)
{
  symlink = std::move(openSymlinkRx).assume_value();
}
else if (make_error_code(openSymlinkRx.error())
          == std::error_code(
                         ntstatus_file_is_a_directory,
                         ntkernel_error_category::ntkernel_category()))
{
  OUTCOME_TRY(auto &&symlinkPath, llfio::to_win32_path(dirh));
  symlinkPath /= which.leafname;

  OUTCOME_TRY(symlink, llfio::symlink_handle::symlink({}, symlinkPath /*...*/);
}
else
{
  return std::move(openSymlinkRx).as_failure();
}
ned14 commented

My apologies that this didn't work before. As you will see in the commit, the changes needed to fix it were minimal. This was an excellent example of "if you don't test it, it probably doesn't work". Thanks for the bug report!