diff --git a/include/fast_io_driver/install_path/bsd.h b/include/fast_io_driver/install_path/bsd.h index a0615fef..90b1e806 100644 --- a/include/fast_io_driver/install_path/bsd.h +++ b/include/fast_io_driver/install_path/bsd.h @@ -27,7 +27,7 @@ inline ::fast_io::install_path get_module_install_path() char buffer1[PATH_MAX + 1]; char buffer2[PATH_MAX + 1]; char *resolved{}; - int length = -1; + // int length = -1; #if defined(__NetBSD__) int mib[4]{CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME}; diff --git a/include/fast_io_driver/install_path/linux.h b/include/fast_io_driver/install_path/linux.h index f42f7169..42fecf31 100644 --- a/include/fast_io_driver/install_path/linux.h +++ b/include/fast_io_driver/install_path/linux.h @@ -24,7 +24,7 @@ inline ::fast_io::install_path get_module_install_path() char buffer[path_max + 1]; ::fast_io::install_path ret; - using my_ssize_t = ::std::make_signed_t<::std::size_t>; + using my_ssize_t [[maybe_unused]] = ::std::make_signed_t<::std::size_t>; #if defined(__linux__) && defined(__NR_readlink) auto resolved{::fast_io::system_call<__NR_readlink, my_ssize_t>("/proc/self/exe", buffer, path_max)}; system_call_throw_error(resolved); diff --git a/include/fast_io_hosted/filesystem/nt_at.h b/include/fast_io_hosted/filesystem/nt_at.h index 3be2375a..09f7f3aa 100644 --- a/include/fast_io_hosted/filesystem/nt_at.h +++ b/include/fast_io_hosted/filesystem/nt_at.h @@ -56,35 +56,52 @@ namespace win32::nt::details inline constexpr nt_open_mode calculate_nt_delete_flag(nt_at_flags flags) noexcept { + // FILE_DELETE_ON_CLOSE is not used here. Instead, use FILE_DISPOSITION_INFORMATION to control deletion! + + // FILE_DELETE_ON_CLOSE schedules deletion at handle close. + // The actual delete operation happens inside NtClose, which does not provide detailed error codes. + // Therefore, you cannot reliably retrieve the actual delete failure reason. + + // POSIX requires unlinkat() to always operate in no-follow mode (symlinks are + // unconditionally unlinked as directory entries and never resolved). Therefore, + // we must enforce the same no-follow behavior here. + nt_open_mode mode{ - .DesiredAccess = 0x00010000, // FILE_GENERIC_READ - .FileAttributes = 0x80, // FILE_ATTRIBUTE_NORMAL - .ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE - .CreateDisposition = 0x00000001, /*OPEN_EXISTING => FILE_OPEN*/ - .CreateOptions = 0x00001000 /*FILE_DELETE_ON_CLOSE*/ + .DesiredAccess = 0x00010000 | 0x00100000, // DELETE | SYNCHRONIZE + .FileAttributes = 0x80, // FILE_ATTRIBUTE_NORMAL + .ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + .CreateDisposition = 0x00000001, // OPEN_EXISTING => FILE_OPEN + .CreateOptions = 0x00000020 | 0x00004000 | 0x00200000 // FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_FLAG_OPEN_REPARSE_POINT }; - if ((flags & nt_at_flags::symlink_nofollow) == nt_at_flags::symlink_nofollow) - { - mode.CreateOptions |= 0x00200000; // FILE_FLAG_OPEN_REPARSE_POINT => FILE_OPEN_REPARSE_POINT (0x00200000) - } + if ((flags & nt_at_flags::removedir) == nt_at_flags::removedir) { - mode.CreateOptions |= 0x00004000; // FILE_OPEN_FOR_BACKUP_INTENT mode.CreateOptions |= 0x00000001; // FILE_DIRECTORY_FILE } else { - mode.CreateOptions |= 0x00000040; // FILE_NON_DIRECTORY_FILE 0x00000040 + mode.CreateOptions |= 0x00000040; // FILE_NON_DIRECTORY_FILE } + return mode; } template inline void nt_unlinkat_impl(void *dirhd, char16_t const *path_c_str, ::std::size_t path_size, nt_at_flags flags, bool kernel) { - auto status{nt_close( - nt_call_determine_kernel_callback(dirhd, path_c_str, path_size, kernel, nt_create_callback{calculate_nt_delete_flag(flags)}))}; - if (status) + ::fast_io::basic_nt_family_file<(zw ? nt_family::zw : nt_family::nt), char> file{ + nt_call_determine_kernel_callback(dirhd, path_c_str, path_size, kernel, nt_create_callback{calculate_nt_delete_flag(flags)})}; + + ::fast_io::win32::nt::io_status_block IoStatusBlock; // no initialization needed + ::fast_io::win32::nt::file_disposition_information fdi{.DeleteFile = true}; + + auto status{::fast_io::win32::nt::nt_set_information_file(file.native_handle(), + __builtin_addressof(IoStatusBlock), + __builtin_addressof(fdi), + static_cast<::std::uint_least32_t>(sizeof(fdi)), + ::fast_io::win32::nt::file_information_class::FileDispositionInformation)}; + + if (status) [[unlikely]] { throw_nt_error(status); } @@ -107,7 +124,7 @@ inline void nt_mkdirat_impl(void *dirhd, char16_t const *path_c_str, ::std::size } auto status{nt_close(nt_call_determine_kernel_callback(dirhd, path_c_str, path_size, kernel, nt_create_callback{m_dir_mode}))}; - + if (status) { throw_nt_error(status); @@ -777,10 +794,10 @@ inline ::fast_io::details::basic_ct_string nt_readlinkat_impl(void *d { #if !defined(_WIN32_WINNT) || _WIN32_WINNT > 0x0600 constexpr ::fast_io::win32::nt::details::nt_open_mode md{ - .DesiredAccess = 0x00100000 | 0x0080, // SYNCHRONIZE | FILE_READ_ATTRIBUTES - .FileAttributes = 0x80, // FILE_ATTRIBUTE_NORMAL - .ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE - .CreateDisposition = 0x00000001, // OPEN_EXISTING => FILE_OPEN + .DesiredAccess = 0x00100000 | 0x0080, // SYNCHRONIZE | FILE_READ_ATTRIBUTES + .FileAttributes = 0x80, // FILE_ATTRIBUTE_NORMAL + .ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + .CreateDisposition = 0x00000001, // OPEN_EXISTING => FILE_OPEN .CreateOptions = 0x00200000 | 0x00000020 // FILE_FLAG_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT }; @@ -834,7 +851,7 @@ inline ::fast_io::details::basic_ct_string nt_readlinkat_impl(void *d #endif else { - throw_nt_error(0xC0000002); + throw_nt_error(0xC0000275u /*STATUS_NOT_A_REPARSE_POINT*/); } return {}; @@ -851,7 +868,7 @@ inline ::fast_io::details::basic_ct_string nt_readlinkat_impl(void *d ::fast_io::basic_nt_family_file<(zw ? nt_family::zw : nt_family::nt), char> file{ nt_call_determine_kernel_callback(dirhd, path_c_str, path_size, kernel, nt_create_callback{md})}; - throw_nt_error(0xC0000002); + throw_nt_error(0xC0000275u /*STATUS_NOT_A_REPARSE_POINT*/); return {}; #endif diff --git a/include/fast_io_hosted/process/process/posix.h b/include/fast_io_hosted/process/process/posix.h index 161b9bf2..e9fd621a 100644 --- a/include/fast_io_hosted/process/process/posix.h +++ b/include/fast_io_hosted/process/process/posix.h @@ -8,6 +8,11 @@ namespace fast_io namespace posix { +// The statement about argu[] and enopl] being constants is included to make explicit to future writers of language bindings that these objects are completely constant. +// Due toa limitation of the ISOC standard, it is not possible to state that idea in standard C. Specifying two levels of const-qualification for the argol] and enopll +// parameters for the exec functions may seem to be the natural choice, given that these functions do not modify either the array of pointers or the characters to which the +// function points, but this would disallow existing correct code. Instead, only the array of pointers is noted as constant. + #if defined(__DARWIN_C_LEVEL) || defined(__MSDOS__) extern int libc_fexecve(int fd, char *const *argv, char *const *envp) noexcept __asm__("_fexecve"); extern int libc_execveat(int dirfd, char const *pathname, char *const *argv, char *const *envp, int flags) noexcept __asm__("_execveat"); @@ -130,7 +135,7 @@ namespace details * - The returned path may differ from original open() argument due to symlinks or namespaces. */ -inline void portable_fd_path(int fd, char *buf, ::std::size_t bufsz) +inline void portable_fd_path([[maybe_unused]] int fd, char *buf, ::std::size_t bufsz) { if (buf == nullptr || bufsz == 0u) [[unlikely]] { @@ -179,7 +184,7 @@ inline void portable_fd_path(int fd, char *buf, ::std::size_t bufsz) ::fast_io::obuffer_view linkpath_ov{linkpath, linkpath + all_sz}; ::fast_io::operations::print_freestanding(linkpath_ov, path_str, fd, ::fast_io::mnp::chvw(::fast_io::char_literal_v)); - using my_ssize_t = ::std::make_signed_t<::std::size_t>; + using my_ssize_t [[maybe_unused]] = ::std::make_signed_t<::std::size_t>; #if defined(__linux__) && defined(__NR_readlink) auto resolved{::fast_io::system_call<__NR_readlink, my_ssize_t>(linkpath, buf, bufsz - 1u)}; @@ -763,7 +768,7 @@ inline void vfork_and_execveat(pid_t &pid, int dirfd, char const *cstr, char con flags |= AT_SYMLINK_NOFOLLOW; } - auto ret{::fast_io::posix::libc_execveat(dirfd, cstr, args, envp, flags)}; + auto ret{::fast_io::posix::libc_execveat(dirfd, cstr, const_cast(args), const_cast(envp), flags)}; if (ret == -1) { t_errno = errno; @@ -786,7 +791,7 @@ inline void vfork_and_execveat(pid_t &pid, int dirfd, char const *cstr, char con flags |= AT_SYMLINK_NOFOLLOW; } - auto ret{::fast_io::posix::libc_execveat(dirfd, cstr, args, envp, flags)}; + auto ret{::fast_io::posix::libc_execveat(dirfd, cstr, const_cast(args), const_cast(envp), flags)}; if (ret == -1) { t_errno = errno;