Skip to content

Commit d2796f2

Browse files
authored
Refactor file size retrieval and enhance POSIX socket error handling (#1200)
* 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. * Update win32.h * Add GetDiskFreeSpace functions to win32 APIs for improved disk space retrieval * update posix truncate * update posix * update posix_at * 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. * 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.
1 parent 79919c0 commit d2796f2

File tree

9 files changed

+337
-68
lines changed

9 files changed

+337
-68
lines changed

include/fast_io_hosted/file_loaders/file_size.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ inline ::std::size_t file_size(::fast_io::basic_win32_family_io_observer<family,
170170
template <nt_family family, ::std::integral char_type>
171171
inline ::std::size_t file_size(::fast_io::basic_nt_family_io_observer<family, char_type> observer)
172172
{
173-
return win32::nt::details::nt_load_file_get_file_size(observer.handle);
173+
constexpr bool zw{family == nt_family::zw};
174+
return win32::nt::details::nt_load_file_get_file_size<zw>(observer.handle);
174175
}
175176
#endif
176177

include/fast_io_hosted/filesystem/posix_at.h

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,13 @@ inline void posix_faccessat_impl(int dirfd, char const *pathname, int mode, int
186186
{
187187
system_call_throw_error(
188188
#if defined(__linux__) && defined(__NR_faccessat2)
189-
system_call<__NR_faccessat2, int>
189+
system_call<__NR_faccessat2, int>(dirfd, pathname, mode, flags)
190190
#elif defined(__linux__) && defined(__NR_faccessat)
191-
system_call<__NR_faccessat, int>
191+
system_call<__NR_faccessat, int>(dirfd, pathname, mode)
192192
#else
193-
::fast_io::posix::libc_faccessat
193+
::fast_io::posix::libc_faccessat(dirfd, pathname, mode, flags)
194194
#endif
195-
(dirfd, pathname, mode, flags));
195+
);
196196
}
197197

198198
#if defined(__wasi__) && !defined(__wasilibc_unmodified_upstream)
@@ -336,19 +336,19 @@ inline void posix_unlinkat_impl(int dirfd, char const *path, int flags)
336336

337337
namespace details
338338
{
339-
inline constexpr struct timespec unix_timestamp_to_struct_timespec64(unix_timestamp stmp) noexcept
339+
inline constexpr struct timespec unix_timestamp_to_struct_timespec(unix_timestamp stmp) noexcept
340340
{
341341
constexpr ::std::uint_least64_t mul_factor{uint_least64_subseconds_per_second / 1000000000u};
342342
return {static_cast<::std::time_t>(stmp.seconds),
343-
static_cast<long>(static_cast<long unsigned>((stmp.subseconds) / mul_factor))};
343+
static_cast<long>(static_cast<long unsigned>(stmp.subseconds / mul_factor))};
344344
}
345345

346346
inline
347347
#if defined(UTIME_NOW) && defined(UTIME_OMIT)
348348
constexpr
349349
#endif
350350
struct timespec
351-
unix_timestamp_to_struct_timespec64([[maybe_unused]] unix_timestamp_option opt) noexcept
351+
unix_timestamp_to_struct_timespec([[maybe_unused]] unix_timestamp_option opt) noexcept
352352
{
353353
#if defined(UTIME_NOW) && defined(UTIME_OMIT)
354354
switch (opt.flags)
@@ -357,13 +357,54 @@ inline
357357
return {.tv_sec = 0, .tv_nsec = UTIME_NOW};
358358
case utime_flags::omit:
359359
return {.tv_sec = 0, .tv_nsec = UTIME_OMIT};
360+
default:
361+
return unix_timestamp_to_struct_timespec(opt.timestamp);
362+
}
363+
#else
364+
throw_posix_error(EINVAL);
365+
#endif
366+
}
367+
368+
#if defined(__linux__) && defined(__NR_utimensat_time64)
369+
370+
// https://github.com/torvalds/linux/blob/07e27ad16399afcd693be20211b0dfae63e0615f/include/uapi/linux/time_types.h#L7
371+
// https://github.com/qemu/qemu/blob/ab8008b231e758e03c87c1c483c03afdd9c02e19/linux-user/syscall_defs.h#L251
372+
// https://github.com/bminor/glibc/blob/b7e0ec907ba94b6fcc6142bbaddea995bcc3cef3/include/struct___timespec64.h#L15
373+
struct kernel_timespec64
374+
{
375+
::std::int_least64_t tv_sec;
376+
::std::int_least64_t tv_nsec;
377+
};
378+
379+
inline constexpr kernel_timespec64 unix_timestamp_to_struct_timespec64(unix_timestamp stmp) noexcept
380+
{
381+
constexpr ::std::uint_least64_t mul_factor{uint_least64_subseconds_per_second / 1000000000u};
382+
return {static_cast<::std::int_least64_t>(stmp.seconds),
383+
static_cast<::std::int_least64_t>(stmp.subseconds / mul_factor)};
384+
}
385+
386+
inline
387+
#if defined(UTIME_NOW) && defined(UTIME_OMIT)
388+
constexpr
389+
#endif
390+
kernel_timespec64
391+
unix_timestamp_to_struct_timespec64([[maybe_unused]] unix_timestamp_option opt) noexcept
392+
{
393+
#if defined(UTIME_NOW) && defined(UTIME_OMIT)
394+
switch (opt.flags)
395+
{
396+
case utime_flags::now:
397+
return {.tv_sec = 0, .tv_nsec = static_cast<::std::int_least64_t>(UTIME_NOW)};
398+
case utime_flags::omit:
399+
return {.tv_sec = 0, .tv_nsec = static_cast<::std::int_least64_t>(UTIME_OMIT)};
360400
default:
361401
return unix_timestamp_to_struct_timespec64(opt.timestamp);
362402
}
363403
#else
364404
throw_posix_error(EINVAL);
365405
#endif
366406
}
407+
#endif
367408

368409
} // namespace details
369410

@@ -375,11 +416,21 @@ inline void posix_utimensat_impl(int dirfd, char const *path, unix_timestamp_opt
375416
{
376417
throw_posix_error(EINVAL);
377418
}
378-
struct timespec ts[2]{
419+
420+
#if defined(__linux__) && defined(__NR_utimensat_time64)
421+
details::kernel_timespec64 ts[2]{
379422
details::unix_timestamp_to_struct_timespec64(last_access_time),
380423
details::unix_timestamp_to_struct_timespec64(last_modification_time),
381424
};
425+
details::kernel_timespec64 *tsptr{ts};
426+
#else
427+
struct timespec ts[2]{
428+
details::unix_timestamp_to_struct_timespec(last_access_time),
429+
details::unix_timestamp_to_struct_timespec(last_modification_time),
430+
};
382431
struct timespec *tsptr{ts};
432+
#endif
433+
383434
system_call_throw_error(
384435
#if defined(__linux__)
385436
#if defined(__NR_utimensat_time64)

include/fast_io_hosted/platforms/nt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ inline constexpr nt_open_mode calculate_nt_open_mode(open_mode_perms ompm) noexc
8888
constexpr auto default_write_attribute{0x00020000L /*READ_CONTROL*/ | 0x0002 /*FILE_WRITE_DATA*/ | 0x0004 /*FILE_APPEND_DATA*/};
8989
constexpr auto default_read_attribute{0x00020000L /*READ_CONTROL*/ | 0x0001 /*FILE_READ_DATA*/};
9090

91-
mode.DesiredAccess |= 0x00100000L /*SYNCHRONIZE*/ | 0x0080 /*FILE_READ_ATTRIBUTES*/;
91+
mode.DesiredAccess |= 0x00100000L /*SYNCHRONIZE*/ | 0x0080 /*FILE_READ_ATTRIBUTES*/ | 0x0100 /*FILE_WRITE_ATTRIBUTES*/;
9292

9393
if ((value & open_mode::no_shared_read) == open_mode::none)
9494
{

include/fast_io_hosted/platforms/posix.h

Lines changed: 117 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,11 +1377,114 @@ inline void posix_truncate_impl(int fd, ::fast_io::uintfpos_t size)
13771377
}
13781378
#endif
13791379

1380-
#elif defined(__linux__) && defined(__NR_ftruncate64)
1381-
system_call_throw_error(system_call<__NR_ftruncate64, int>(fd, size));
1382-
#elif defined(__linux__) && defined(__NR_ftruncate)
1383-
system_call_throw_error(system_call<__NR_ftruncate, int>(fd, size));
1380+
#elif defined(__linux__)
1381+
if constexpr (sizeof(::std::size_t) >= sizeof(::std::uint_least64_t))
1382+
{
1383+
#if defined(__NR_ftruncate)
1384+
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max())
1385+
{
1386+
if (size > ::std::numeric_limits<::std::uint_least64_t>::max())
1387+
{
1388+
throw_posix_error(EINVAL);
1389+
}
1390+
}
1391+
1392+
system_call_throw_error(system_call<__NR_ftruncate, int>(fd, static_cast<::std::uint_least64_t>(size)));
1393+
#else
1394+
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<off_t>::max())
1395+
{
1396+
if (size > ::std::numeric_limits<off_t>::max())
1397+
{
1398+
throw_posix_error(EINVAL);
1399+
}
1400+
}
1401+
1402+
if (noexcept_call(ftruncate, fd, static_cast<off_t>(size)) < 0)
1403+
{
1404+
throw_posix_error();
1405+
}
1406+
#endif
1407+
}
1408+
else if constexpr (sizeof(::std::size_t) >= sizeof(::std::uint_least32_t))
1409+
{
1410+
#if defined(__NR_ftruncate64)
1411+
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least64_t>::max())
1412+
{
1413+
if (size > ::std::numeric_limits<::std::uint_least64_t>::max())
1414+
{
1415+
throw_posix_error(EINVAL);
1416+
}
1417+
}
1418+
1419+
::std::uint_least64_t size_u64{static_cast<::std::uint_least64_t>(size)};
1420+
::std::uint_least32_t size_u32_low{static_cast<::std::uint_least32_t>(size_u64)};
1421+
::std::uint_least32_t size_u32_high{static_cast<::std::uint_least32_t>(size_u64 >> 32u)};
1422+
1423+
int result_syscall; // no initlize
1424+
1425+
if constexpr (::std::endian::native == ::std::endian::big)
1426+
{
1427+
/* 3 args: fd, size (high, low) */
1428+
result_syscall = ::fast_io::system_call<__NR_ftruncate64, int>(fd, size_u32_high, size_u32_low);
1429+
}
1430+
else
1431+
{
1432+
/* 3 args: fd, size (low, high) */
1433+
result_syscall = ::fast_io::system_call<__NR_ftruncate64, int>(fd, size_u32_low, size_u32_high);
1434+
}
1435+
1436+
system_call_throw_error(result_syscall);
1437+
1438+
#elif defined(__NR_ftruncate)
1439+
1440+
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<::std::uint_least32_t>::max())
1441+
{
1442+
if (size > ::std::numeric_limits<::std::uint_least32_t>::max())
1443+
{
1444+
throw_posix_error(EINVAL);
1445+
}
1446+
}
1447+
1448+
system_call_throw_error(system_call<__NR_ftruncate, int>(fd, static_cast<::std::uint_least32_t>(size)));
1449+
#else
1450+
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<off_t>::max())
1451+
{
1452+
if (size > ::std::numeric_limits<off_t>::max())
1453+
{
1454+
throw_posix_error(EINVAL);
1455+
}
1456+
}
1457+
1458+
if (noexcept_call(ftruncate, fd, static_cast<off_t>(size)) < 0)
1459+
{
1460+
throw_posix_error();
1461+
}
1462+
#endif
1463+
}
1464+
else
1465+
{
1466+
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<off_t>::max())
1467+
{
1468+
if (size > ::std::numeric_limits<off_t>::max())
1469+
{
1470+
throw_posix_error(EINVAL);
1471+
}
1472+
}
1473+
1474+
if (noexcept_call(ftruncate, fd, static_cast<off_t>(size)) < 0)
1475+
{
1476+
throw_posix_error();
1477+
}
1478+
}
13841479
#else
1480+
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<off_t>::max())
1481+
{
1482+
if (size > ::std::numeric_limits<off_t>::max())
1483+
{
1484+
throw_posix_error(EINVAL);
1485+
}
1486+
}
1487+
13851488
if (noexcept_call(ftruncate, fd, static_cast<off_t>(size)) < 0)
13861489
{
13871490
throw_posix_error();
@@ -1412,20 +1515,30 @@ class basic_posix_family_pipe
14121515
#if defined(__wasi__)
14131516
throw_posix_error(ENOTSUP);
14141517
#else
1518+
14151519
int a2[2]{-1, -1};
1520+
14161521
#if (defined(_WIN32) && !defined(__WINE__) && !defined(__BIONIC__)) && !defined(__CYGWIN__)
14171522
if (noexcept_call(::_pipe, a2, 131072u, _O_BINARY) == -1)
1523+
{
14181524
throw_posix_error();
1525+
}
14191526
#elif defined(__linux__)
14201527
if (noexcept_call(::pipe2, a2, O_CLOEXEC) == -1)
1528+
{
14211529
throw_posix_error();
1530+
}
14221531
#elif (defined(__MSDOS__) || defined(__DJGPP__)) || defined(__NEWLIB__)
14231532
if (noexcept_call(::pipe, a2) == -1)
1533+
{
14241534
throw_posix_error();
1535+
}
14251536
#else
14261537
{
14271538
if (noexcept_call(::pipe, a2) == -1)
1539+
{
14281540
throw_posix_error();
1541+
}
14291542
::fast_io::posix_file_factory fd0(a2[0]);
14301543
::fast_io::posix_file_factory fd1(a2[1]);
14311544
::fast_io::details::sys_fcntl(fd0.fd, F_SETFD, FD_CLOEXEC);

include/fast_io_hosted/platforms/posix/win32.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ namespace details
88

99
inline ::std::byte *posix_pread_bytes_impl(int fd, ::std::byte *first, ::std::byte *last, ::fast_io::intfpos_t off)
1010
{
11-
return ::fast_io::win32::details::pread_some_bytes_impl(::fast_io::details::my_get_osfile_handle(fd), first, last,
12-
off);
11+
// Here, functions from the operations module must be selected because Windows 9x may not provide the p-series functions.
12+
return ::fast_io::operations::pread_some_bytes(::fast_io::win32_io_observer{::fast_io::details::my_get_osfile_handle(fd)}, first, last, off);
1313
}
1414

1515
inline ::std::byte const *posix_pwrite_bytes_impl(int fd, ::std::byte const *first, ::std::byte const *last,
1616
::fast_io::intfpos_t off)
1717
{
18-
return ::fast_io::win32::details::pwrite_some_bytes_impl(::fast_io::details::my_get_osfile_handle(fd), first, last,
19-
off);
18+
// Here, functions from the operations module must be selected because Windows 9x may not provide the p-series functions.
19+
return ::fast_io::operations::pwrite_some_bytes(::fast_io::win32_io_observer{::fast_io::details::my_get_osfile_handle(fd)}, first, last, off);
2020
}
2121

2222
} // namespace details

include/fast_io_hosted/platforms/posix_mapping.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ inline ::std::byte *sys_mmap(void *addr, ::std::size_t len, int prot, int flags,
4444
}
4545
}
4646
auto ret{reinterpret_cast<::std::byte *>(
47-
::mmap(addr, len, prot, flags, fd, static_cast<off_t>(static_cast<my_make_unsigned_t<off_t>>(offset))))};
47+
::fast_io::noexcept_call(::mmap, addr, len, prot, flags, fd, static_cast<off_t>(static_cast<my_make_unsigned_t<off_t>>(offset))))};
4848
if (ret == MAP_FAILED)
4949
{
5050
throw_posix_error();

include/fast_io_hosted/platforms/posix_netmode.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ inline int sys_socket(int domain, int type, int protocol)
639639
system_call_throw_error(fd);
640640
return fd;
641641
#else
642-
int fd{socket(domain, type, protocol)};
642+
int fd{::fast_io::noexcept_call(::socket, domain, type, protocol)};
643643
if (fd == -1)
644644
{
645645
throw_posix_error();
@@ -661,7 +661,7 @@ inline ::std::size_t posix_socket_write_impl(int fd, void const *data, ::std::si
661661
system_call_throw_error(written);
662662
return static_cast<::std::size_t>(written);
663663
#else
664-
::std::ptrdiff_t written{send(fd, data, to_write, 0)};
664+
::std::ptrdiff_t written{::fast_io::noexcept_call(::send, fd, data, to_write, 0)};
665665
if (written < 0)
666666
{
667667
throw_posix_error();
@@ -677,7 +677,7 @@ inline ::std::size_t posix_socket_read_impl(int fd, void *data, ::std::size_t to
677677
system_call_throw_error(written);
678678
return static_cast<::std::size_t>(written);
679679
#else
680-
::std::ptrdiff_t written{recv(fd, data, to_write, 0)};
680+
::std::ptrdiff_t written{::fast_io::noexcept_call(::recv, fd, data, to_write, 0)};
681681
if (written < 0)
682682
{
683683
throw_posix_error();
@@ -696,7 +696,7 @@ inline void posix_connect_posix_socket_impl(int fd, void const *addr, posix_sock
696696
[[__gnu__::__may_alias__]]
697697
#endif
698698
= struct sockaddr const *;
699-
if (::connect(fd, reinterpret_cast<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
699+
if (::fast_io::noexcept_call(::connect, fd, reinterpret_cast<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
700700
{
701701
throw_posix_error();
702702
}
@@ -713,7 +713,7 @@ inline void posix_bind_posix_socket_impl(int fd, void const *addr, posix_socklen
713713
[[__gnu__::__may_alias__]]
714714
#endif
715715
= struct sockaddr const *;
716-
if (::bind(fd, reinterpret_cast<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
716+
if (::fast_io::noexcept_call(::bind, fd, reinterpret_cast<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
717717
{
718718
throw_posix_error();
719719
}
@@ -725,7 +725,7 @@ inline void posix_listen_posix_socket_impl(int fd, int backlog)
725725
#if defined(__linux__) && defined(__NR_listen)
726726
system_call_throw_error(system_call<__NR_listen, int>(fd, backlog));
727727
#else
728-
if (::listen(fd, backlog) == -1)
728+
if (::fast_io::noexcept_call(::listen, fd, backlog) == -1)
729729
{
730730
throw_posix_error();
731731
}
@@ -744,7 +744,7 @@ inline int posix_accept_posix_socket_impl(int fd, void *addr, posix_socklen_t *a
744744
[[__gnu__::__may_alias__]]
745745
#endif
746746
= struct sockaddr *;
747-
int socfd{::accept(fd, reinterpret_cast<sockaddr_alias_ptr>(addr), addrlen)};
747+
int socfd{::fast_io::noexcept_call(::accept, fd, reinterpret_cast<sockaddr_alias_ptr>(addr), addrlen)};
748748
if (socfd == -1)
749749
{
750750
throw_posix_error();
@@ -765,7 +765,7 @@ inline ::std::ptrdiff_t posix_recvfrom_posix_socket_impl(int fd, void *buf, ::st
765765
[[__gnu__::__may_alias__]]
766766
#endif
767767
= struct sockaddr *;
768-
::std::ptrdiff_t ret{::recvfrom(fd, buf, len, flags, reinterpret_cast<sockaddr_alias_ptr>(src_addr), addrlen)};
768+
::std::ptrdiff_t ret{::fast_io::noexcept_call(::recvfrom, fd, buf, len, flags, reinterpret_cast<sockaddr_alias_ptr>(src_addr), addrlen)};
769769
if (ret == -1)
770770
{
771771
throw_posix_error();
@@ -786,7 +786,7 @@ inline ::std::ptrdiff_t posix_sendto_posix_socket_impl(int fd, void const *buf,
786786
[[__gnu__::__may_alias__]]
787787
#endif
788788
= struct sockaddr const *;
789-
::std::ptrdiff_t ret{::sendto(fd, buf, len, flags, reinterpret_cast<sockaddr_const_alias_ptr>(src_addr), addrlen)};
789+
::std::ptrdiff_t ret{::fast_io::noexcept_call(::sendto, fd, buf, len, flags, reinterpret_cast<sockaddr_const_alias_ptr>(src_addr), addrlen)};
790790
if (ret == -1)
791791
{
792792
throw_posix_error();

0 commit comments

Comments
 (0)