Skip to content
3 changes: 2 additions & 1 deletion include/fast_io_hosted/file_loaders/file_size.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ inline ::std::size_t file_size(::fast_io::basic_win32_family_io_observer<family,
template <nt_family family, ::std::integral char_type>
inline ::std::size_t file_size(::fast_io::basic_nt_family_io_observer<family, char_type> 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<zw>(observer.handle);
}
#endif

Expand Down
67 changes: 59 additions & 8 deletions include/fast_io_hosted/filesystem/posix_at.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -336,19 +336,19 @@ 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<long>(static_cast<long unsigned>((stmp.subseconds) / mul_factor))};
static_cast<long>(static_cast<long unsigned>(stmp.subseconds / mul_factor))};
}

inline
#if defined(UTIME_NOW) && defined(UTIME_OMIT)
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)
Expand All @@ -357,13 +357,54 @@ 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
// 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;
::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);
}
#else
throw_posix_error(EINVAL);
#endif
}
#endif

} // namespace details

Expand All @@ -375,11 +416,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)
Expand Down
2 changes: 1 addition & 1 deletion include/fast_io_hosted/platforms/nt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
121 changes: 117 additions & 4 deletions include/fast_io_hosted/platforms/posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<off_t>::max())
{
if (size > ::std::numeric_limits<off_t>::max())
{
throw_posix_error(EINVAL);
}
}

if (noexcept_call(ftruncate, fd, static_cast<off_t>(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<off_t>::max())
{
if (size > ::std::numeric_limits<off_t>::max())
{
throw_posix_error(EINVAL);
}
}

if (noexcept_call(ftruncate, fd, static_cast<off_t>(size)) < 0)
{
throw_posix_error();
}
#endif
}
else
{
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<off_t>::max())
{
if (size > ::std::numeric_limits<off_t>::max())
{
throw_posix_error(EINVAL);
}
}

if (noexcept_call(ftruncate, fd, static_cast<off_t>(size)) < 0)
{
throw_posix_error();
}
}
#else
if constexpr (::std::numeric_limits<::fast_io::uintfpos_t>::max() > ::std::numeric_limits<off_t>::max())
{
if (size > ::std::numeric_limits<off_t>::max())
{
throw_posix_error(EINVAL);
}
}

if (noexcept_call(ftruncate, fd, static_cast<off_t>(size)) < 0)
{
throw_posix_error();
Expand Down Expand Up @@ -1412,20 +1515,30 @@ 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)
{
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);
Expand Down
8 changes: 4 additions & 4 deletions include/fast_io_hosted/platforms/posix/win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion include/fast_io_hosted/platforms/posix_mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<off_t>(static_cast<my_make_unsigned_t<off_t>>(offset))))};
::fast_io::noexcept_call(::mmap, addr, len, prot, flags, fd, static_cast<off_t>(static_cast<my_make_unsigned_t<off_t>>(offset))))};
if (ret == MAP_FAILED)
{
throw_posix_error();
Expand Down
18 changes: 9 additions & 9 deletions include/fast_io_hosted/platforms/posix_netmode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
if (::fast_io::noexcept_call(::connect, fd, reinterpret_cast<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
{
throw_posix_error();
}
Expand All @@ -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<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
if (::fast_io::noexcept_call(::bind, fd, reinterpret_cast<sockaddr_alias_const_ptr>(addr), addrlen) == -1)
{
throw_posix_error();
}
Expand All @@ -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();
}
Expand All @@ -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<sockaddr_alias_ptr>(addr), addrlen)};
int socfd{::fast_io::noexcept_call(::accept, fd, reinterpret_cast<sockaddr_alias_ptr>(addr), addrlen)};
if (socfd == -1)
{
throw_posix_error();
Expand All @@ -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<sockaddr_alias_ptr>(src_addr), addrlen)};
::std::ptrdiff_t ret{::fast_io::noexcept_call(::recvfrom, fd, buf, len, flags, reinterpret_cast<sockaddr_alias_ptr>(src_addr), addrlen)};
if (ret == -1)
{
throw_posix_error();
Expand All @@ -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<sockaddr_const_alias_ptr>(src_addr), addrlen)};
::std::ptrdiff_t ret{::fast_io::noexcept_call(::sendto, fd, buf, len, flags, reinterpret_cast<sockaddr_const_alias_ptr>(src_addr), addrlen)};
if (ret == -1)
{
throw_posix_error();
Expand Down
Loading
Loading