From def131fd969a75c7fffe21a72a930d30f04b38a7 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Mon, 22 Sep 2025 00:04:26 +0800 Subject: [PATCH 1/8] Refactor file size retrieval and enhance POSIX socket error handling - Updated `file_size` function to use a template parameter for NT family file size retrieval. - Replaced direct socket calls with `::fast_io::noexcept_call` in POSIX networking functions to improve error handling. - Introduced a `find_struct_guard` for automatic resource management in Win32 directory handling. - Added `win32_9xa_dir_file_status_impl` to retrieve file status for Win32 9xa directory handles, enhancing compatibility with POSIX file status functions. --- .../fast_io_hosted/file_loaders/file_size.h | 3 +- .../fast_io_hosted/platforms/posix_netmode.h | 18 +- include/fast_io_hosted/platforms/win32.h | 157 ++++++++++++++---- include/fast_io_hosted/platforms/win32/apis.h | 6 + 4 files changed, 142 insertions(+), 42 deletions(-) diff --git a/include/fast_io_hosted/file_loaders/file_size.h b/include/fast_io_hosted/file_loaders/file_size.h index f997264db..74a16f93c 100644 --- a/include/fast_io_hosted/file_loaders/file_size.h +++ b/include/fast_io_hosted/file_loaders/file_size.h @@ -170,7 +170,8 @@ inline ::std::size_t file_size(::fast_io::basic_win32_family_io_observer inline ::std::size_t file_size(::fast_io::basic_nt_family_io_observer observer) { - return win32::nt::details::nt_load_file_get_file_size(observer.handle); + constexpr bool zw{family == nt_family::zw}; + return win32::nt::details::nt_load_file_get_file_size(observer.handle); } #endif diff --git a/include/fast_io_hosted/platforms/posix_netmode.h b/include/fast_io_hosted/platforms/posix_netmode.h index 101693dd6..3c5691e4b 100644 --- a/include/fast_io_hosted/platforms/posix_netmode.h +++ b/include/fast_io_hosted/platforms/posix_netmode.h @@ -639,7 +639,7 @@ inline int sys_socket(int domain, int type, int protocol) system_call_throw_error(fd); return fd; #else - int fd{socket(domain, type, protocol)}; + int fd{::fast_io::noexcept_call(::socket, domain, type, protocol)}; if (fd == -1) { throw_posix_error(); @@ -661,7 +661,7 @@ inline ::std::size_t posix_socket_write_impl(int fd, void const *data, ::std::si system_call_throw_error(written); return static_cast<::std::size_t>(written); #else - ::std::ptrdiff_t written{send(fd, data, to_write, 0)}; + ::std::ptrdiff_t written{::fast_io::noexcept_call(::send, fd, data, to_write, 0)}; if (written < 0) { throw_posix_error(); @@ -677,7 +677,7 @@ inline ::std::size_t posix_socket_read_impl(int fd, void *data, ::std::size_t to system_call_throw_error(written); return static_cast<::std::size_t>(written); #else - ::std::ptrdiff_t written{recv(fd, data, to_write, 0)}; + ::std::ptrdiff_t written{::fast_io::noexcept_call(::recv, fd, data, to_write, 0)}; if (written < 0) { throw_posix_error(); @@ -696,7 +696,7 @@ inline void posix_connect_posix_socket_impl(int fd, void const *addr, posix_sock [[__gnu__::__may_alias__]] #endif = struct sockaddr const *; - if (::connect(fd, reinterpret_cast(addr), addrlen) == -1) + if (::fast_io::noexcept_call(::connect, fd, reinterpret_cast(addr), addrlen) == -1) { throw_posix_error(); } @@ -713,7 +713,7 @@ inline void posix_bind_posix_socket_impl(int fd, void const *addr, posix_socklen [[__gnu__::__may_alias__]] #endif = struct sockaddr const *; - if (::bind(fd, reinterpret_cast(addr), addrlen) == -1) + if (::fast_io::noexcept_call(::bind, fd, reinterpret_cast(addr), addrlen) == -1) { throw_posix_error(); } @@ -725,7 +725,7 @@ inline void posix_listen_posix_socket_impl(int fd, int backlog) #if defined(__linux__) && defined(__NR_listen) system_call_throw_error(system_call<__NR_listen, int>(fd, backlog)); #else - if (::listen(fd, backlog) == -1) + if (::fast_io::noexcept_call(::listen, fd, backlog) == -1) { throw_posix_error(); } @@ -744,7 +744,7 @@ inline int posix_accept_posix_socket_impl(int fd, void *addr, posix_socklen_t *a [[__gnu__::__may_alias__]] #endif = struct sockaddr *; - int socfd{::accept(fd, reinterpret_cast(addr), addrlen)}; + int socfd{::fast_io::noexcept_call(::accept, fd, reinterpret_cast(addr), addrlen)}; if (socfd == -1) { throw_posix_error(); @@ -765,7 +765,7 @@ inline ::std::ptrdiff_t posix_recvfrom_posix_socket_impl(int fd, void *buf, ::st [[__gnu__::__may_alias__]] #endif = struct sockaddr *; - ::std::ptrdiff_t ret{::recvfrom(fd, buf, len, flags, reinterpret_cast(src_addr), addrlen)}; + ::std::ptrdiff_t ret{::fast_io::noexcept_call(::recvfrom, fd, buf, len, flags, reinterpret_cast(src_addr), addrlen)}; if (ret == -1) { throw_posix_error(); @@ -786,7 +786,7 @@ inline ::std::ptrdiff_t posix_sendto_posix_socket_impl(int fd, void const *buf, [[__gnu__::__may_alias__]] #endif = struct sockaddr const *; - ::std::ptrdiff_t ret{::sendto(fd, buf, len, flags, reinterpret_cast(src_addr), addrlen)}; + ::std::ptrdiff_t ret{::fast_io::noexcept_call(::sendto, fd, buf, len, flags, reinterpret_cast(src_addr), addrlen)}; if (ret == -1) { throw_posix_error(); diff --git a/include/fast_io_hosted/platforms/win32.h b/include/fast_io_hosted/platforms/win32.h index 0b240aaf9..973502d87 100644 --- a/include/fast_io_hosted/platforms/win32.h +++ b/include/fast_io_hosted/platforms/win32.h @@ -710,15 +710,23 @@ inline ::fast_io::intfpos_t seek_impl(void *handle, ::fast_io::intfpos_t offset, throw_win32_error(0x00000057); } } + ::std::int_least32_t distance_to_move_high{}; constexpr ::std::uint_least32_t invalid{UINT_LEAST32_MAX}; - if (::fast_io::win32::SetFilePointer(handle, static_cast<::std::int_least32_t>(offset), - __builtin_addressof(distance_to_move_high), - static_cast<::std::uint_least32_t>(s)) == invalid) + auto const low{::fast_io::win32::SetFilePointer(handle, static_cast<::std::int_least32_t>(offset), + __builtin_addressof(distance_to_move_high), static_cast<::std::uint_least32_t>(s))}; + + if (low == invalid) [[unlikely]] { - throw_win32_error(); + auto const err{::fast_io::win32::GetLastError()}; + if (err != 0u) [[unlikely]] + { + throw_win32_error(err); + } } - return static_cast<::fast_io::intfpos_t>(distance_to_move_high); + + ::std::uint_least64_t const combined{(static_cast<::std::uint_least64_t>(static_cast<::std::uint_least32_t>(distance_to_move_high)) << 32u) | static_cast<::std::uint_least32_t>(low)}; + return static_cast<::fast_io::intfpos_t>(combined); #else if constexpr (sizeof(::fast_io::intfpos_t) > sizeof(::std::int_least64_t)) { @@ -729,14 +737,14 @@ inline ::fast_io::intfpos_t seek_impl(void *handle, ::fast_io::intfpos_t offset, throw_win32_error(0x00000057); } } - ::std::int_least64_t distance_to_move_high{}; + ::std::int_least64_t distance_full{}; if (!::fast_io::win32::SetFilePointerEx(handle, static_cast<::std::int_least64_t>(offset), - __builtin_addressof(distance_to_move_high), + __builtin_addressof(distance_full), static_cast<::std::uint_least32_t>(s))) { throw_win32_error(); } - return static_cast<::fast_io::intfpos_t>(distance_to_move_high); + return static_cast<::fast_io::intfpos_t>(distance_full); #endif } @@ -954,6 +962,25 @@ struct win32_9xa_dir_handle namespace win32::details { +struct find_struct_guard +{ + void *file_struct{}; + + inline explicit constexpr find_struct_guard(void *fs) noexcept : file_struct{fs} + {} + + find_struct_guard(find_struct_guard const &) = delete; + find_struct_guard &operator=(find_struct_guard const &) = delete; + + inline ~find_struct_guard() + { + if (file_struct && file_struct != reinterpret_cast(static_cast<::std::ptrdiff_t>(-1))) [[likely]] + { + ::fast_io::win32::FindClose(file_struct); + } + } +}; + inline void check_win32_9xa_dir_is_valid(win32_9xa_dir_handle const &h) { ::fast_io::win32::win32_find_dataa wfda{}; @@ -969,7 +996,7 @@ inline void check_win32_9xa_dir_is_valid(win32_9xa_dir_handle const &h) } } -inline bool get_win32_9xa_dir_validity(win32_9xa_dir_handle const &h) +[[nodiscard]] inline bool get_win32_9xa_dir_validity(win32_9xa_dir_handle const &h) noexcept { ::fast_io::win32::win32_find_dataa wfda{}; tlc_win32_9xa_dir_handle_path_str temp_find_path{concat_tlc_win32_9xa_dir_handle_path_str(h.path, u8"\\*")}; @@ -991,9 +1018,9 @@ inline void close_win32_9xa_dir_handle(win32_9xa_dir_handle &h) noexcept(!throw_ if constexpr (throw_eh) { // Make sure to successfully close even if an exception is thrown. - bool const is_win32_9xa_dir_validid{get_win32_9xa_dir_validity(h)}; + bool const is_win32_9xa_dir_valid{get_win32_9xa_dir_validity(h)}; h.path.clear(); - if (!is_win32_9xa_dir_validid) [[unlikely]] + if (!is_win32_9xa_dir_valid) [[unlikely]] { throw_win32_error(0x5); } @@ -1004,7 +1031,7 @@ inline void close_win32_9xa_dir_handle(win32_9xa_dir_handle &h) noexcept(!throw_ } } -inline win32_9xa_dir_handle win32_9xa_dir_dup_impl(win32_9xa_dir_handle const &h) +inline win32_9xa_dir_handle win32_9xa_dir_dup_impl(win32_9xa_dir_handle const &h) { check_win32_9xa_dir_is_valid(h); return {h.path}; @@ -1017,25 +1044,6 @@ inline win32_9xa_dir_handle win32_9xa_dir_dup2_impl(win32_9xa_dir_handle const & return temp; } -struct find_struct_guard -{ - void *file_struct{}; - - find_struct_guard(find_struct_guard const &) = delete; - find_struct_guard &operator=(find_struct_guard const &) = delete; - - inline ~find_struct_guard() - { - if (file_struct) [[likely]] - { - if (!::fast_io::win32::FindClose(file_struct)) - { - throw_win32_error(); - } - } - } -}; - inline win32_9xa_dir_handle basic_win32_9xa_create_dir_file_impl(char const *filename_c_str, ::std::size_t filename_c_str_len) { using char8_t_const_may_alias_ptr @@ -1545,7 +1553,7 @@ class basic_win32_family_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public template inline void truncate(basic_win32_family_io_observer handle, ::fast_io::uintfpos_t size) { - win32::details::seek_impl(handle, size, seekdir::beg); + win32::details::seek_impl(handle.handle, size, seekdir::beg); if (!::fast_io::win32::SetEndOfFile(handle.handle)) { throw_win32_error(); @@ -1698,6 +1706,86 @@ inline posix_file_status win32_status_impl(void *__restrict handle) 0}; } +inline posix_file_status win32_9xa_dir_file_status_impl(win32_9xa_dir_handle const &handle) +{ + ::fast_io::posix_file_status tmp_file{}; + + // find data + ::fast_io::win32::win32_find_dataa wfda{}; + tlc_win32_9xa_dir_handle_path_str temp_find_path{concat_tlc_win32_9xa_dir_handle_path_str(handle.path, u8"\\*")}; + auto find_struct{::fast_io::win32::FindFirstFileA(reinterpret_cast(temp_find_path.c_str()), __builtin_addressof(wfda))}; + if (find_struct == reinterpret_cast(static_cast<::std::ptrdiff_t>(-1))) [[unlikely]] + { + throw_win32_error(0x5); + } + else + { + find_struct_guard guard{find_struct}; + // The first piece of information obtained by findfirstfile is current path ('.') + + ::std::underlying_type_t pm{0444}; + if ((wfda.dwFileAttributes & 0x1) == 0x0) + { + pm |= 0222; + } + + tmp_file.perm = static_cast(pm); + tmp_file.type = ::fast_io::file_type::directory; + tmp_file.nlink = 1u; + tmp_file.size = static_cast<::std::uintmax_t>((static_cast<::std::uint_least64_t>(wfda.nFileSizeHigh) << 32u) | wfda.nFileSizeLow); + tmp_file.blksize = 512u; + tmp_file.blocks = (tmp_file.size + 511u) / 512u; + tmp_file.atim = to_unix_timestamp(wfda.ftLastAccessTime); + tmp_file.mtim = to_unix_timestamp(wfda.ftLastWriteTime); + tmp_file.ctim = tmp_file.mtim; + tmp_file.btim = to_unix_timestamp(wfda.ftCreationTime); + + // find_struct destructor will close the handle + } + + // dev + using char_const_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char const *; + + using char_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char *; + + // Use A APIs and a char buffer; avoid multiplying by sizeof(char8_t) + constexpr ::std::size_t tmp_path_char_size{260u}; + char tmp_path_char[tmp_path_char_size]; + + auto const full_len{::fast_io::win32::GetFullPathNameA(reinterpret_cast(handle.path.c_str()), tmp_path_char_size, tmp_path_char, nullptr)}; + if (!full_len || full_len >= tmp_path_char_size) [[unlikely]] + { + return tmp_file; + } + + // Build root like "C:\\" safely + if (full_len < 3u) [[unlikely]] + { + return tmp_file; + } + + tmp_path_char[3u] = static_cast(u8'\0'); + + ::std::uint_least32_t serial{}; + + if (!::fast_io::win32::GetVolumeInformationA(tmp_path_char, nullptr, 0u, __builtin_addressof(serial), nullptr, nullptr, nullptr, 0u)) + { + return tmp_file; + } + + tmp_file.dev = static_cast<::std::uintmax_t>(serial); + + return tmp_file; +} + /* Thanks Fseuio for providing source code. */ @@ -1763,6 +1851,11 @@ inline posix_file_status status(basic_win32_family_io_observer return win32::details::win32_status_impl(wiob.handle); } +inline posix_file_status status(win32_9xa_dir_io_observer w9xiob) +{ + return win32::details::win32_9xa_dir_file_status_impl(w9xiob.handle); +} + template class basic_win32_family_pipe { diff --git a/include/fast_io_hosted/platforms/win32/apis.h b/include/fast_io_hosted/platforms/win32/apis.h index b72785e27..240a62ff1 100644 --- a/include/fast_io_hosted/platforms/win32/apis.h +++ b/include/fast_io_hosted/platforms/win32/apis.h @@ -174,4 +174,10 @@ FAST_IO_DLLIMPORT char16_t *FAST_IO_WINSTDCALL GetEnvironmentStringsW() noexcept FAST_IO_DLLIMPORT char *FAST_IO_WINSTDCALL GetEnvironmentStringsA() noexcept FAST_IO_WINSTDCALL_RENAME(GetEnvironmentStringsA, 0); FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL FreeEnvironmentStringsW(char16_t*) noexcept FAST_IO_WINSTDCALL_RENAME(FreeEnvironmentStringsW, 4); FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL FreeEnvironmentStringsA(char*) noexcept FAST_IO_WINSTDCALL_RENAME(FreeEnvironmentStringsA, 4); +FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL getsockopt(::std::size_t, int, int, char*, int*) noexcept FAST_IO_WINSTDCALL_RENAME(getsockopt, 20); +FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL GetFullPathNameW(char16_t const*, ::std::uint_least32_t, char16_t*, char16_t**) noexcept FAST_IO_WINSTDCALL_RENAME(GetFullPathNameW, 16); +FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL GetFullPathNameA(char const*, ::std::uint_least32_t, char*, char**) noexcept FAST_IO_WINSTDCALL_RENAME(GetFullPathNameA, 16); +FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL GetVolumeInformationW(char16_t const*, char16_t*, ::std::uint_least32_t, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*, char16_t*, ::std::uint_least32_t) noexcept FAST_IO_WINSTDCALL_RENAME(GetVolumeInformationW, 32); +FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL GetVolumeInformationA(char const*, char*, ::std::uint_least32_t, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*, char*, ::std::uint_least32_t) noexcept FAST_IO_WINSTDCALL_RENAME(GetVolumeInformationA, 32); + } // namespace fast_io::win32 From 4dc7bd190daa82608b429c5bd812ab94ec219ddb Mon Sep 17 00:00:00 2001 From: MacroModel <33865334+MacroModel@users.noreply.github.com> Date: Mon, 22 Sep 2025 10:21:41 +0800 Subject: [PATCH 2/8] Update win32.h --- include/fast_io_hosted/platforms/win32.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/fast_io_hosted/platforms/win32.h b/include/fast_io_hosted/platforms/win32.h index 973502d87..0c21c370f 100644 --- a/include/fast_io_hosted/platforms/win32.h +++ b/include/fast_io_hosted/platforms/win32.h @@ -1750,12 +1750,6 @@ inline posix_file_status win32_9xa_dir_file_status_impl(win32_9xa_dir_handle con #endif = char const *; - using char_may_alias_ptr -#if __has_cpp_attribute(__gnu__::__may_alias__) - [[__gnu__::__may_alias__]] -#endif - = char *; - // Use A APIs and a char buffer; avoid multiplying by sizeof(char8_t) constexpr ::std::size_t tmp_path_char_size{260u}; char tmp_path_char[tmp_path_char_size]; From 30821a05caeb052ade7eceadfc298e4eb17433a2 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Mon, 22 Sep 2025 15:41:43 +0800 Subject: [PATCH 3/8] Add GetDiskFreeSpace functions to win32 APIs for improved disk space retrieval --- include/fast_io_hosted/platforms/win32.h | 42 ++++++++++--------- include/fast_io_hosted/platforms/win32/apis.h | 2 + 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/include/fast_io_hosted/platforms/win32.h b/include/fast_io_hosted/platforms/win32.h index 0c21c370f..4ede97513 100644 --- a/include/fast_io_hosted/platforms/win32.h +++ b/include/fast_io_hosted/platforms/win32.h @@ -1732,9 +1732,9 @@ inline posix_file_status win32_9xa_dir_file_status_impl(win32_9xa_dir_handle con tmp_file.perm = static_cast(pm); tmp_file.type = ::fast_io::file_type::directory; tmp_file.nlink = 1u; - tmp_file.size = static_cast<::std::uintmax_t>((static_cast<::std::uint_least64_t>(wfda.nFileSizeHigh) << 32u) | wfda.nFileSizeLow); - tmp_file.blksize = 512u; - tmp_file.blocks = (tmp_file.size + 511u) / 512u; + tmp_file.size = static_cast<::std::uintmax_t>((static_cast<::std::uint_least64_t>(wfda.nFileSizeHigh) << 32u) | wfda.nFileSizeLow); // always zero + tmp_file.blksize = 512u; // default + tmp_file.blocks = (tmp_file.size + 511u) / 512u; // default tmp_file.atim = to_unix_timestamp(wfda.ftLastAccessTime); tmp_file.mtim = to_unix_timestamp(wfda.ftLastWriteTime); tmp_file.ctim = tmp_file.mtim; @@ -1755,28 +1755,30 @@ inline posix_file_status win32_9xa_dir_file_status_impl(win32_9xa_dir_handle con char tmp_path_char[tmp_path_char_size]; auto const full_len{::fast_io::win32::GetFullPathNameA(reinterpret_cast(handle.path.c_str()), tmp_path_char_size, tmp_path_char, nullptr)}; - if (!full_len || full_len >= tmp_path_char_size) [[unlikely]] - { - return tmp_file; - } - // Build root like "C:\\" safely - if (full_len < 3u) [[unlikely]] + if (full_len > 2u && full_len <= tmp_path_char_size && ::fast_io::char_category::is_c_alpha(tmp_path_char[0])) [[likely]] { - return tmp_file; - } + // Build root like "C:\\" safely + // The Character size of the tmp_path_char_size can accommodate the size + tmp_path_char[3u] = static_cast(u8'\0'); - tmp_path_char[3u] = static_cast(u8'\0'); - - ::std::uint_least32_t serial{}; - - if (!::fast_io::win32::GetVolumeInformationA(tmp_path_char, nullptr, 0u, __builtin_addressof(serial), nullptr, nullptr, nullptr, 0u)) - { - return tmp_file; + // get dev + ::std::uint_least32_t serial{}; + if (::fast_io::win32::GetVolumeInformationA(tmp_path_char, nullptr, 0u, __builtin_addressof(serial), nullptr, nullptr, nullptr, 0u)) [[likely]] + { + tmp_file.dev = static_cast<::std::uintmax_t>(serial); + } + + // get blocksize + ::std::uint_least32_t sector_per_cluster{}; + ::std::uint_least32_t bytes_per_sector{}; + if (::fast_io::win32::GetDiskFreeSpaceA(tmp_path_char, __builtin_addressof(sector_per_cluster), __builtin_addressof(bytes_per_sector), nullptr, nullptr)) [[likely]] + { + tmp_file.blksize = static_cast<::std::uintmax_t>(bytes_per_sector) * static_cast<::std::uintmax_t>(sector_per_cluster); + tmp_file.blocks = (tmp_file.blksize + 511u) / 512u; + } } - tmp_file.dev = static_cast<::std::uintmax_t>(serial); - return tmp_file; } diff --git a/include/fast_io_hosted/platforms/win32/apis.h b/include/fast_io_hosted/platforms/win32/apis.h index 240a62ff1..7439d8dc3 100644 --- a/include/fast_io_hosted/platforms/win32/apis.h +++ b/include/fast_io_hosted/platforms/win32/apis.h @@ -179,5 +179,7 @@ FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL GetFullPathNameW(char FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL GetFullPathNameA(char const*, ::std::uint_least32_t, char*, char**) noexcept FAST_IO_WINSTDCALL_RENAME(GetFullPathNameA, 16); FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL GetVolumeInformationW(char16_t const*, char16_t*, ::std::uint_least32_t, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*, char16_t*, ::std::uint_least32_t) noexcept FAST_IO_WINSTDCALL_RENAME(GetVolumeInformationW, 32); FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL GetVolumeInformationA(char const*, char*, ::std::uint_least32_t, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*, char*, ::std::uint_least32_t) noexcept FAST_IO_WINSTDCALL_RENAME(GetVolumeInformationA, 32); +FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL GetDiskFreeSpaceW(char16_t const*, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*) noexcept FAST_IO_WINSTDCALL_RENAME(GetDiskFreeSpaceW, 20); +FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL GetDiskFreeSpaceA(char const*, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*, ::std::uint_least32_t*) noexcept FAST_IO_WINSTDCALL_RENAME(GetDiskFreeSpaceA, 20); } // namespace fast_io::win32 From e428eb4fb596316fce21b4fd35abb5c083b41ba2 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Mon, 22 Sep 2025 18:41:54 +0800 Subject: [PATCH 4/8] update posix truncate --- include/fast_io_hosted/platforms/posix.h | 116 ++++++++++++++++++++++- 1 file changed, 112 insertions(+), 4 deletions(-) diff --git a/include/fast_io_hosted/platforms/posix.h b/include/fast_io_hosted/platforms/posix.h index 0b4c8b984..00d098d6b 100644 --- a/include/fast_io_hosted/platforms/posix.h +++ b/include/fast_io_hosted/platforms/posix.h @@ -1377,11 +1377,114 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) } #endif -#elif defined(__linux__) && defined(__NR_ftruncate64) - system_call_throw_error(system_call<__NR_ftruncate64, int>(fd, size)); -#elif defined(__linux__) && defined(__NR_ftruncate) - system_call_throw_error(system_call<__NR_ftruncate, int>(fd, size)); +#elif defined(__linux__) + if constexpr(sizeof(::std::size_t) >= sizeof(::std::uint_least64_t)) + { +#if defined(__NR_ftruncate) + if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max()) + { + if (size > ::std::numeric_limits<::std::uint_least64_t>::max()) + { + throw_posix_error(EINVAL); + } + } + + system_call_throw_error(system_call<__NR_ftruncate, int>(fd, static_cast<::std::uint_least64_t>(size))); +#else + if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + { + if (size > ::std::numeric_limits::max()) + { + throw_posix_error(EINVAL); + } + } + + if (noexcept_call(ftruncate, fd, static_cast(size)) < 0) + { + throw_posix_error(); + } +#endif + } + else if constexpr (sizeof(::std::size_t) >= sizeof(::std::uint_least32_t)) + { +#if defined(__NR_ftruncate64) + if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max()) + { + if (size > ::std::numeric_limits<::std::uint_least64_t>::max()) + { + throw_posix_error(EINVAL); + } + } + + ::std::uint_least64_t size_u64{static_cast<::std::uint_least64_t>(size)}; + ::std::uint_least32_t size_u32_low{static_cast<::std::uint_least32_t>(size_u64)}; + ::std::uint_least32_t size_u32_high{static_cast<::std::uint_least32_t>(size_u64 >> 32u)}; + + int result_syscall; // no initlize + + if constexpr(::std::endian::native == ::std::endian::big) + { + /* 3 args: fd, size (high, low) */ + result_syscall = ::fast_io::system_call<__NR_ftruncate64, int>(fd, size_u32_high, size_u32_low); + } + else + { + /* 3 args: fd, size (low, high) */ + result_syscall = ::fast_io::system_call<__NR_ftruncate64, int>(fd, size_u32_low, size_u32_high); + } + + system_call_throw_error(result_syscall); + +#elif defined(__NR_ftruncate) + + if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least32_t>::max()) + { + if (size > ::std::numeric_limits<::std::uint_least32_t>::max()) + { + throw_posix_error(EINVAL); + } + } + + system_call_throw_error(system_call<__NR_ftruncate, int>(fd, static_cast<::std::uint_least32_t>(size))); #else + if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + { + if (size > ::std::numeric_limits::max()) + { + throw_posix_error(EINVAL); + } + } + + if (noexcept_call(ftruncate, fd, static_cast(size)) < 0) + { + throw_posix_error(); + } +#endif + } + else + { + if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + { + if (size > ::std::numeric_limits::max()) + { + throw_posix_error(EINVAL); + } + } + + if (noexcept_call(ftruncate, fd, static_cast(size)) < 0) + { + throw_posix_error(); + } + } +#else + if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + { + if (size > ::std::numeric_limits::max()) + { + throw_posix_error(EINVAL); + } + } + if (noexcept_call(ftruncate, fd, static_cast(size)) < 0) { throw_posix_error(); @@ -1412,7 +1515,9 @@ class basic_posix_family_pipe #if defined(__wasi__) throw_posix_error(ENOTSUP); #else + int a2[2]{-1, -1}; + #if (defined(_WIN32) && !defined(__WINE__) && !defined(__BIONIC__)) && !defined(__CYGWIN__) if (noexcept_call(::_pipe, a2, 131072u, _O_BINARY) == -1) #elif defined(__linux__) @@ -1422,7 +1527,10 @@ class basic_posix_family_pipe #else if (noexcept_call(::pipe, a2) == -1 || ::fast_io::details::sys_fcntl(a2[0], F_SETFD, FD_CLOEXEC) == -1 || ::fast_io::details::sys_fcntl(a2[1], F_SETFD, FD_CLOEXEC) == -1) #endif + { throw_posix_error(); + } + pipes->fd = *a2; pipes[1].fd = a2[1]; #endif From d1229c222952021359ab7c2c37bd13333f724763 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Mon, 22 Sep 2025 19:16:49 +0800 Subject: [PATCH 5/8] update posix --- include/fast_io_hosted/filesystem/posix_at.h | 8 ++++---- include/fast_io_hosted/platforms/posix_mapping.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/fast_io_hosted/filesystem/posix_at.h b/include/fast_io_hosted/filesystem/posix_at.h index 3f8b95314..96a6f89e8 100644 --- a/include/fast_io_hosted/filesystem/posix_at.h +++ b/include/fast_io_hosted/filesystem/posix_at.h @@ -186,13 +186,13 @@ inline void posix_faccessat_impl(int dirfd, char const *pathname, int mode, int { system_call_throw_error( #if defined(__linux__) && defined(__NR_faccessat2) - system_call<__NR_faccessat2, int> + system_call<__NR_faccessat2, int>(dirfd, pathname, mode, flags) #elif defined(__linux__) && defined(__NR_faccessat) - system_call<__NR_faccessat, int> + system_call<__NR_faccessat, int>(dirfd, pathname, mode) #else - ::fast_io::posix::libc_faccessat + ::fast_io::posix::libc_faccessat(dirfd, pathname, mode, flags) #endif - (dirfd, pathname, mode, flags)); + ); } #if defined(__wasi__) && !defined(__wasilibc_unmodified_upstream) diff --git a/include/fast_io_hosted/platforms/posix_mapping.h b/include/fast_io_hosted/platforms/posix_mapping.h index 97f005ee3..031b7c26f 100644 --- a/include/fast_io_hosted/platforms/posix_mapping.h +++ b/include/fast_io_hosted/platforms/posix_mapping.h @@ -44,7 +44,7 @@ inline ::std::byte *sys_mmap(void *addr, ::std::size_t len, int prot, int flags, } } auto ret{reinterpret_cast<::std::byte *>( - ::mmap(addr, len, prot, flags, fd, static_cast(static_cast>(offset))))}; + ::fast_io::noexcept_call(::mmap, addr, len, prot, flags, fd, static_cast(static_cast>(offset))))}; if (ret == MAP_FAILED) { throw_posix_error(); From a13c016bd2f243470d4b5fdcc1a66cfcc321bf6a Mon Sep 17 00:00:00 2001 From: MacroModel Date: Mon, 22 Sep 2025 21:00:27 +0800 Subject: [PATCH 6/8] update posix_at --- include/fast_io_hosted/filesystem/posix_at.h | 57 ++++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/include/fast_io_hosted/filesystem/posix_at.h b/include/fast_io_hosted/filesystem/posix_at.h index 96a6f89e8..30907f1ac 100644 --- a/include/fast_io_hosted/filesystem/posix_at.h +++ b/include/fast_io_hosted/filesystem/posix_at.h @@ -336,11 +336,11 @@ inline void posix_unlinkat_impl(int dirfd, char const *path, int flags) namespace details { -inline constexpr struct timespec unix_timestamp_to_struct_timespec64(unix_timestamp stmp) noexcept +inline constexpr struct timespec unix_timestamp_to_struct_timespec(unix_timestamp stmp) noexcept { constexpr ::std::uint_least64_t mul_factor{uint_least64_subseconds_per_second / 1000000000u}; return {static_cast<::std::time_t>(stmp.seconds), - static_cast(static_cast((stmp.subseconds) / mul_factor))}; + static_cast(static_cast(stmp.subseconds / mul_factor))}; } inline @@ -348,7 +348,7 @@ inline constexpr #endif struct timespec - unix_timestamp_to_struct_timespec64([[maybe_unused]] unix_timestamp_option opt) noexcept + unix_timestamp_to_struct_timespec([[maybe_unused]] unix_timestamp_option opt) noexcept { #if defined(UTIME_NOW) && defined(UTIME_OMIT) switch (opt.flags) @@ -357,6 +357,44 @@ inline return {.tv_sec = 0, .tv_nsec = UTIME_NOW}; case utime_flags::omit: return {.tv_sec = 0, .tv_nsec = UTIME_OMIT}; + default: + return unix_timestamp_to_struct_timespec(opt.timestamp); + } +#else + throw_posix_error(EINVAL); +#endif +} + +#if defined(__linux__) && defined(__NR_utimensat_time64) + +// https://github.com/torvalds/linux/blob/07e27ad16399afcd693be20211b0dfae63e0615f/include/uapi/linux/time_types.h#L7 +struct kernel_timespec64 +{ + ::std::int_least64_t tv_sec; + ::std::int_least64_t tv_nsec; +}; + +inline constexpr kernel_timespec64 unix_timestamp_to_struct_timespec64(unix_timestamp stmp) noexcept +{ + constexpr ::std::uint_least64_t mul_factor{uint_least64_subseconds_per_second / 1000000000u}; + return {static_cast<::std::int_least64_t>(stmp.seconds), + static_cast<::std::int_least64_t>(stmp.subseconds / mul_factor)}; +} + +inline +#if defined(UTIME_NOW) && defined(UTIME_OMIT) + constexpr +#endif + kernel_timespec64 + unix_timestamp_to_struct_timespec64([[maybe_unused]] unix_timestamp_option opt) noexcept +{ +#if defined(UTIME_NOW) && defined(UTIME_OMIT) + switch (opt.flags) + { + case utime_flags::now: + return {.tv_sec = 0, .tv_nsec = static_cast<::std::int_least64_t>(UTIME_NOW)}; + case utime_flags::omit: + return {.tv_sec = 0, .tv_nsec = static_cast<::std::int_least64_t>(UTIME_OMIT)}; default: return unix_timestamp_to_struct_timespec64(opt.timestamp); } @@ -364,6 +402,7 @@ inline throw_posix_error(EINVAL); #endif } +#endif } // namespace details @@ -375,11 +414,21 @@ inline void posix_utimensat_impl(int dirfd, char const *path, unix_timestamp_opt { throw_posix_error(EINVAL); } - struct timespec ts[2]{ + +#if defined(__linux__) && defined(__NR_utimensat_time64) + details::kernel_timespec64 ts[2]{ details::unix_timestamp_to_struct_timespec64(last_access_time), details::unix_timestamp_to_struct_timespec64(last_modification_time), }; + details::kernel_timespec64 *tsptr{ts}; +#else + struct timespec ts[2]{ + details::unix_timestamp_to_struct_timespec(last_access_time), + details::unix_timestamp_to_struct_timespec(last_modification_time), + }; struct timespec *tsptr{ts}; +#endif + system_call_throw_error( #if defined(__linux__) #if defined(__NR_utimensat_time64) From 26ba3f2e968367db59b09923b1097677708ebbd4 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Mon, 29 Sep 2025 20:14:25 +0800 Subject: [PATCH 7/8] Enhance Windows compatibility and update function implementations - Added references for `kernel_timespec64` in `posix_at.h`. - Updated `calculate_nt_open_mode` in `nt.h` to include `FILE_WRITE_ATTRIBUTES`. - Renamed read and write functions in `win32.h` for clarity and to reflect their specific implementations. - Adjusted `posix_pread_bytes_impl` and `posix_pwrite_bytes_impl` to use operations module functions for Windows 9x compatibility. --- include/fast_io_hosted/filesystem/posix_at.h | 2 ++ include/fast_io_hosted/platforms/nt.h | 2 +- .../fast_io_hosted/platforms/posix/win32.h | 8 +++---- include/fast_io_hosted/platforms/win32.h | 23 ++++++++++++------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/fast_io_hosted/filesystem/posix_at.h b/include/fast_io_hosted/filesystem/posix_at.h index 30907f1ac..8d4edd426 100644 --- a/include/fast_io_hosted/filesystem/posix_at.h +++ b/include/fast_io_hosted/filesystem/posix_at.h @@ -368,6 +368,8 @@ inline #if defined(__linux__) && defined(__NR_utimensat_time64) // https://github.com/torvalds/linux/blob/07e27ad16399afcd693be20211b0dfae63e0615f/include/uapi/linux/time_types.h#L7 +// https://github.com/qemu/qemu/blob/ab8008b231e758e03c87c1c483c03afdd9c02e19/linux-user/syscall_defs.h#L251 +// https://github.com/bminor/glibc/blob/b7e0ec907ba94b6fcc6142bbaddea995bcc3cef3/include/struct___timespec64.h#L15 struct kernel_timespec64 { ::std::int_least64_t tv_sec; diff --git a/include/fast_io_hosted/platforms/nt.h b/include/fast_io_hosted/platforms/nt.h index b025ee895..439e2e9bf 100644 --- a/include/fast_io_hosted/platforms/nt.h +++ b/include/fast_io_hosted/platforms/nt.h @@ -88,7 +88,7 @@ inline constexpr nt_open_mode calculate_nt_open_mode(open_mode_perms ompm) noexc constexpr auto default_write_attribute{0x00020000L /*READ_CONTROL*/ | 0x0002 /*FILE_WRITE_DATA*/ | 0x0004 /*FILE_APPEND_DATA*/}; constexpr auto default_read_attribute{0x00020000L /*READ_CONTROL*/ | 0x0001 /*FILE_READ_DATA*/}; - mode.DesiredAccess |= 0x00100000L /*SYNCHRONIZE*/ | 0x0080 /*FILE_READ_ATTRIBUTES*/; + mode.DesiredAccess |= 0x00100000L /*SYNCHRONIZE*/ | 0x0080 /*FILE_READ_ATTRIBUTES*/ | 0x0100 /*FILE_WRITE_ATTRIBUTES*/; if ((value & open_mode::no_shared_read) == open_mode::none) { diff --git a/include/fast_io_hosted/platforms/posix/win32.h b/include/fast_io_hosted/platforms/posix/win32.h index ee0c1d680..38bd80443 100644 --- a/include/fast_io_hosted/platforms/posix/win32.h +++ b/include/fast_io_hosted/platforms/posix/win32.h @@ -8,15 +8,15 @@ namespace details inline ::std::byte *posix_pread_bytes_impl(int fd, ::std::byte *first, ::std::byte *last, ::fast_io::intfpos_t off) { - return ::fast_io::win32::details::pread_some_bytes_impl(::fast_io::details::my_get_osfile_handle(fd), first, last, - off); + // Here, functions from the operations module must be selected because Windows 9x may not provide the p-series functions. + return ::fast_io::operations::pread_some_bytes(::fast_io::win32_io_observer{::fast_io::details::my_get_osfile_handle(fd)}, first, last, off); } inline ::std::byte const *posix_pwrite_bytes_impl(int fd, ::std::byte const *first, ::std::byte const *last, ::fast_io::intfpos_t off) { - return ::fast_io::win32::details::pwrite_some_bytes_impl(::fast_io::details::my_get_osfile_handle(fd), first, last, - off); + // Here, functions from the operations module must be selected because Windows 9x may not provide the p-series functions. + return ::fast_io::operations::pwrite_some_bytes(::fast_io::win32_io_observer{::fast_io::details::my_get_osfile_handle(fd)}, first, last, off); } } // namespace details diff --git a/include/fast_io_hosted/platforms/win32.h b/include/fast_io_hosted/platforms/win32.h index 4ede97513..2d28f064c 100644 --- a/include/fast_io_hosted/platforms/win32.h +++ b/include/fast_io_hosted/platforms/win32.h @@ -775,14 +775,15 @@ inline ::std::byte *read_or_pread_some_bytes_common_impl(void *__restrict handle return first + number_of_bytes; } -inline ::std::byte *read_some_bytes_impl(void *__restrict handle, ::std::byte *first, ::std::byte *last) +inline ::std::byte *win32_read_some_bytes_impl(void *__restrict handle, ::std::byte *first, ::std::byte *last) { return ::fast_io::win32::details::read_or_pread_some_bytes_common_impl(handle, first, last, nullptr); } -inline ::std::byte *pread_some_bytes_impl(void *__restrict handle, ::std::byte *first, ::std::byte *last, +inline ::std::byte *win32_ntw_pread_some_bytes_impl(void *__restrict handle, ::std::byte *first, ::std::byte *last, ::fast_io::intfpos_t off) { + // The use of overlapped behavior is not supported in Windows 95. ::fast_io::win32::overlapped overlap{}; ::fast_io::win32::details::win32_calculate_offset_impl(handle, overlap, off); return ::fast_io::win32::details::read_or_pread_some_bytes_common_impl(handle, first, last, @@ -803,15 +804,16 @@ inline ::std::byte const *write_or_pwrite_some_bytes_common_impl(void *__restric return first + number_of_bytes; } -inline ::std::byte const *write_some_bytes_impl(void *__restrict handle, ::std::byte const *first, +inline ::std::byte const *win32_write_some_bytes_impl(void *__restrict handle, ::std::byte const *first, ::std::byte const *last) { return ::fast_io::win32::details::write_or_pwrite_some_bytes_common_impl(handle, first, last, nullptr); } -inline ::std::byte const *pwrite_some_bytes_impl(void *__restrict handle, ::std::byte const *first, +inline ::std::byte const *win32_ntw_pwrite_some_bytes_impl(void *__restrict handle, ::std::byte const *first, ::std::byte const *last, ::fast_io::intfpos_t off) { + // The use of overlapped behavior is not supported in Windows 95. ::fast_io::win32::overlapped overlap{}; ::fast_io::win32::details::win32_calculate_offset_impl(handle, overlap, off); return ::fast_io::win32::details::write_or_pwrite_some_bytes_common_impl(handle, first, last, @@ -824,14 +826,14 @@ template inline ::std::byte *read_some_bytes_underflow_define(basic_win32_family_io_observer wiob, ::std::byte *first, ::std::byte *last) { - return ::fast_io::win32::details::read_some_bytes_impl(wiob.handle, first, last); + return ::fast_io::win32::details::win32_read_some_bytes_impl(wiob.handle, first, last); } template inline ::std::byte const *write_some_bytes_overflow_define(basic_win32_family_io_observer wiob, ::std::byte const *first, ::std::byte const *last) { - return ::fast_io::win32::details::write_some_bytes_impl(wiob.handle, first, last); + return ::fast_io::win32::details::win32_write_some_bytes_impl(wiob.handle, first, last); } template @@ -845,11 +847,15 @@ inline ::fast_io::intfpos_t io_stream_seek_bytes_define(basic_win32_family_io_ob I am not confident that i understand semantics correctly. Disabled first and test it later */ +// Windows 9x does not support atomic p-series functions. When using operation::p-series functions, +// they will be emulated through seek and non-p-series functions. +// For Win9x, use the operation::p series functions, which automatically combine seek operations with non-p series functions. +#if !defined(_WIN32_WINDOWS) template inline ::std::byte *pread_some_bytes_underflow_define(basic_win32_family_io_observer niob, ::std::byte *first, ::std::byte *last, ::fast_io::intfpos_t off) { - return ::fast_io::win32::details::pread_some_bytes_impl(niob.handle, first, last, off); + return ::fast_io::win32::details::win32_ntw_pread_some_bytes_impl(niob.handle, first, last, off); } template @@ -857,8 +863,9 @@ inline ::std::byte const *pwrite_some_bytes_overflow_define(basic_win32_family_i ::std::byte const *first, ::std::byte const *last, ::fast_io::intfpos_t off) { - return ::fast_io::win32::details::pwrite_some_bytes_impl(niob.handle, first, last, off); + return ::fast_io::win32::details::win32_ntw_pwrite_some_bytes_impl(niob.handle, first, last, off); } +#endif template inline constexpr basic_win32_family_io_observer From 824e60f25e0381c37af44d29c9de66ba7885c889 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Mon, 29 Sep 2025 20:35:52 +0800 Subject: [PATCH 8/8] Refactor POSIX truncate implementation for improved readability - Adjusted spacing in conditional statements for consistency. - Enhanced error handling in POSIX pipe setup by ensuring proper exception throwing. - No functional changes; focus on code clarity and maintainability. --- include/fast_io_hosted/platforms/posix.h | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/include/fast_io_hosted/platforms/posix.h b/include/fast_io_hosted/platforms/posix.h index e4c36edb0..cb2f60542 100644 --- a/include/fast_io_hosted/platforms/posix.h +++ b/include/fast_io_hosted/platforms/posix.h @@ -1378,12 +1378,12 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) #endif #elif defined(__linux__) - if constexpr(sizeof(::std::size_t) >= sizeof(::std::uint_least64_t)) + if constexpr (sizeof(::std::size_t) >= sizeof(::std::uint_least64_t)) { #if defined(__NR_ftruncate) - if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max()) + if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max()) { - if (size > ::std::numeric_limits<::std::uint_least64_t>::max()) + if (size > ::std::numeric_limits<::std::uint_least64_t>::max()) { throw_posix_error(EINVAL); } @@ -1391,7 +1391,7 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) system_call_throw_error(system_call<__NR_ftruncate, int>(fd, static_cast<::std::uint_least64_t>(size))); #else - if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) { if (size > ::std::numeric_limits::max()) { @@ -1408,7 +1408,7 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) else if constexpr (sizeof(::std::size_t) >= sizeof(::std::uint_least32_t)) { #if defined(__NR_ftruncate64) - if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max()) + if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max()) { if (size > ::std::numeric_limits<::std::uint_least64_t>::max()) { @@ -1420,9 +1420,9 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) ::std::uint_least32_t size_u32_low{static_cast<::std::uint_least32_t>(size_u64)}; ::std::uint_least32_t size_u32_high{static_cast<::std::uint_least32_t>(size_u64 >> 32u)}; - int result_syscall; // no initlize + int result_syscall; // no initlize - if constexpr(::std::endian::native == ::std::endian::big) + if constexpr (::std::endian::native == ::std::endian::big) { /* 3 args: fd, size (high, low) */ result_syscall = ::fast_io::system_call<__NR_ftruncate64, int>(fd, size_u32_high, size_u32_low); @@ -1437,7 +1437,7 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) #elif defined(__NR_ftruncate) - if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least32_t>::max()) + if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least32_t>::max()) { if (size > ::std::numeric_limits<::std::uint_least32_t>::max()) { @@ -1447,7 +1447,7 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) system_call_throw_error(system_call<__NR_ftruncate, int>(fd, static_cast<::std::uint_least32_t>(size))); #else - if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) { if (size > ::std::numeric_limits::max()) { @@ -1463,7 +1463,7 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) } else { - if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) { if (size > ::std::numeric_limits::max()) { @@ -1477,7 +1477,7 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size) } } #else - if constexpr(::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) + if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits::max()) { if (size > ::std::numeric_limits::max()) { @@ -1520,17 +1520,25 @@ class basic_posix_family_pipe #if (defined(_WIN32) && !defined(__WINE__) && !defined(__BIONIC__)) && !defined(__CYGWIN__) if (noexcept_call(::_pipe, a2, 131072u, _O_BINARY) == -1) + { throw_posix_error(); + } #elif defined(__linux__) if (noexcept_call(::pipe2, a2, O_CLOEXEC) == -1) + { throw_posix_error(); + } #elif (defined(__MSDOS__) || defined(__DJGPP__)) || defined(__NEWLIB__) if (noexcept_call(::pipe, a2) == -1) + { throw_posix_error(); + } #else { if (noexcept_call(::pipe, a2) == -1) + { throw_posix_error(); + } ::fast_io::posix_file_factory fd0(a2[0]); ::fast_io::posix_file_factory fd1(a2[1]); ::fast_io::details::sys_fcntl(fd0.fd, F_SETFD, FD_CLOEXEC);