Skip to content

Commit

Permalink
support nt_linkat
Browse files Browse the repository at this point in the history
  • Loading branch information
MacroModel committed Nov 12, 2024
1 parent cb266dc commit 51fbb2d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 46 deletions.
95 changes: 52 additions & 43 deletions include/fast_io_hosted/filesystem/nt_at.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,47 +114,51 @@ inline void nt_renameat_impl(void *olddirhd, char16_t const *oldpath_c_str, ::st
{
constexpr nt_open_mode md{
.DesiredAccess = 0x00100000 | 0x0080 | 0x00010000, // SYNCHRONIZE | FILE_READ_ATTRIBUTES | DELETE
.FileAttributes = 0x80, // FILE_READ_ATTRIBUTES
.ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
.CreateDisposition = 0x00000001, // OPEN_EXISTING => FILE_OPEN
.FileAttributes = 0x80, // FILE_READ_ATTRIBUTES
.ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
.CreateDisposition = 0x00000001, // OPEN_EXISTING => FILE_OPEN
};

basic_nt_family_file<zw ? nt_family::zw : nt_family::nt, char> file(
::fast_io::basic_nt_family_file<zw ? nt_family::zw : nt_family::nt, char> file(
nt_call_callback(olddirhd, oldpath_c_str, oldpath_size, nt_create_callback<zw>{md}));

char16_t const *pth_cstr{newpath_c_str};
::std::uint_least32_t pth_size2{static_cast<::std::uint_least32_t>(newpath_size) * sizeof(char16_t)};
::fast_io::details::local_operator_new_array_ptr<char> buffer(sizeof(::fast_io::win32::nt::file_rename_information) + pth_size2 + sizeof(char16_t));
nt_call_callback(
newdirhd, newpath_c_str, newpath_size,
[&](void *directory_hd, win32::nt::unicode_string const *ustr) {
char16_t const *pth_cstr{ustr->Buffer};
::std::uint_least32_t pth_size2{ustr->Length};
::fast_io::details::local_operator_new_array_ptr<char> buffer(sizeof(::fast_io::win32::nt::file_rename_information) + pth_size2 + sizeof(char16_t));

using file_rename_information_may_alias_ptr
using file_rename_information_may_alias_ptr
#if __has_cpp_attribute(__gnu__::__may_alias__)
[[__gnu__::__may_alias__]]
[[__gnu__::__may_alias__]]
#endif
= file_rename_information *;

::fast_io::win32::nt::file_rename_information *info{reinterpret_cast<file_rename_information_may_alias_ptr>(buffer.get())};
info->ReplaceIfExists = 1;
info->RootDirectory = newdirhd;
info->FileNameLength = pth_size2;
::fast_io::freestanding::non_overlapped_copy_n(newpath_c_str, newpath_size + 1, static_cast<char16_t *>(info->FileName));

::fast_io::win32::nt::io_status_block block;
::std::uint_least32_t status{::fast_io::win32::nt::nt_set_information_file<zw>(
file.handle, __builtin_addressof(block), info,
static_cast<::std::uint_least32_t>(sizeof(::fast_io::win32::nt::file_rename_information) + pth_size2 + sizeof(char16_t)), file_information_class::FileRenameInformation)};
if (status) [[unlikely]]
{
throw_nt_error(status);
}
= file_rename_information *;

::fast_io::win32::nt::file_rename_information *info{reinterpret_cast<file_rename_information_may_alias_ptr>(buffer.get())};
info->ReplaceIfExists = 1;
info->RootDirectory = directory_hd;
info->FileNameLength = pth_size2;
::fast_io::freestanding::my_memcpy(info->FileName, pth_cstr, pth_size2 + sizeof(char16_t));

::fast_io::win32::nt::io_status_block block;
::std::uint_least32_t status{::fast_io::win32::nt::nt_set_information_file<zw>(
file.handle, __builtin_addressof(block), info,
static_cast<::std::uint_least32_t>(sizeof(::fast_io::win32::nt::file_rename_information) + pth_size2 + sizeof(char16_t)), file_information_class::FileRenameInformation)};
if (status) [[unlikely]]
{
throw_nt_error(status);
}
});
}

inline constexpr nt_open_mode calculate_nt_link_flag(nt_at_flags flags) noexcept
{
nt_open_mode mode{
.DesiredAccess = 0x00100000 | 0x0100 | 0x0080, // SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES
.FileAttributes = 0x80, // FILE_READ_ATTRIBUTES
.ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
.CreateDisposition = 0x00200000 | 0x00000020, /*OPEN_EXISTING => FILE_OPEN*/
.DesiredAccess = 0x00100000 | 0x0080, // SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES
.FileAttributes = 0x80, // FILE_READ_ATTRIBUTES
.ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
.CreateDisposition = 0x00000001, /*OPEN_EXISTING => FILE_OPEN*/
};
if ((flags & nt_at_flags::symlink_nofollow) != nt_at_flags::symlink_nofollow)
{
Expand All @@ -168,33 +172,38 @@ inline void nt_linkat_impl(void *olddirhd, char16_t const *oldpath_c_str, ::std:
char16_t const *newpath_c_str, ::std::size_t newpath_size, nt_at_flags flags)
{
nt_open_mode const md{calculate_nt_link_flag(flags)};
basic_nt_family_file<(zw ? (nt_family::zw) : (nt_family::nt)), char> file(
::fast_io::basic_nt_family_file<zw ? nt_family::zw : nt_family::nt, char> file(
nt_call_callback(olddirhd, oldpath_c_str, oldpath_size, nt_create_callback<zw>{md}));
nt_call_callback(
newdirhd, newpath_c_str, newpath_size,
[&](void *directory_hd, win32::nt::unicode_string const *ustr) {
char16_t const *pth_cstr{ustr->Buffer};
::std::uint_least32_t pth_size2{ustr->Length};
::fast_io::details::local_operator_new_array_ptr<char> buffer(sizeof(::fast_io::win32::nt::file_link_information) + pth_size2);
::fast_io::win32::nt::file_link_information info{.ReplaceIfExists = false,
.RootDirectory = directory_hd,
.FileNameLength = static_cast<::std::uint_least32_t>(pth_size2)};
::fast_io::details::local_operator_new_array_ptr<char> buffer(sizeof(::fast_io::win32::nt::file_link_information) + pth_size2 + sizeof(char16_t));

::fast_io::details::my_memcpy(buffer.ptr, __builtin_addressof(info), sizeof(::fast_io::win32::nt::file_link_information));
::fast_io::details::my_memcpy(buffer.ptr + sizeof(::fast_io::win32::nt::file_link_information), pth_cstr, pth_size2);

::fast_io::win32::nt::io_status_block block;
using file_link_information_may_alias_ptr
#if __has_cpp_attribute(__gnu__::__may_alias__)
[[__gnu__::__may_alias__]]
#endif
= file_link_information *;

::fast_io::win32::nt::file_link_information *info{reinterpret_cast<file_link_information_may_alias_ptr>(buffer.get())};
info->ReplaceIfExists = 0;
info->RootDirectory = directory_hd;
info->FileNameLength = pth_size2;

::fast_io::freestanding::my_memcpy(info->FileName, pth_cstr, pth_size2 + sizeof(char16_t));

::fast_io::win32::nt::io_status_block block;

::std::uint_least32_t status{::fast_io::win32::nt::nt_set_information_file<zw>(
file.handle, __builtin_addressof(block),
reinterpret_cast<file_link_information_may_alias_ptr>(buffer.ptr),
static_cast<::std::uint_least32_t>(sizeof(info)), file_information_class::FileLinkInformation)};
if (status)
file.handle, __builtin_addressof(block), info,
static_cast<::std::uint_least32_t>(sizeof(::fast_io::win32::nt::file_link_information) + pth_size2 + sizeof(char16_t)), file_information_class::FileLinkInformation)};

if (status) [[unlikely]]
{
throw_nt_error(status);
}
});
}

Expand Down Expand Up @@ -364,7 +373,7 @@ template <::fast_io::constructible_to_os_c_str path_type>
inline void native_fchownat(nt_at_entry, path_type &&, ::std::size_t, ::std::size_t,
[[maybe_unused]] nt_at_flags flags = nt_at_flags::symlink_nofollow)
{
// windows does not use POSIX user group system. stub it and it is perfectly fine. But nt_fchownat,zw_fchownat will
// windows does not use POSIX user group system. stub it and it is perfectly fine. But nt_fchownat, zw_fchownat will
// not be provided since they do not exist.
}

Expand Down
2 changes: 1 addition & 1 deletion include/fast_io_hosted/filesystem/win9x.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct win9x_dirent

::fast_io::win9x_dir_handle d_handle{};
file_type d_type{};
::std::uint_least64_t d_ino{};
[[maybe_unused]] ::std::uint_least64_t d_ino{};
::fast_io::u8string filename{};

~win9x_dirent()
Expand Down
5 changes: 3 additions & 2 deletions include/fast_io_hosted/platforms/nt/nt_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -842,9 +842,10 @@ struct file_fs_volume_information

struct file_link_information
{
::std::uint_least32_t ReplaceIfExists;
void *RootDirectory;
::std::uint_least8_t ReplaceIfExists;
void* RootDirectory;
::std::uint_least32_t FileNameLength;
char16_t FileName[1];
};

struct file_rename_information
Expand Down

0 comments on commit 51fbb2d

Please sign in to comment.