Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions include/fast_io_core_impl/socket/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ struct ip
}

inline explicit constexpr ip() noexcept = default;
inline explicit constexpr ip(ipv4 add)
inline explicit constexpr ip(ipv4 add) noexcept
: address{.address = {.v4 = add.address}, .isv4 = true}, port(add.port)
{}
inline explicit constexpr ip(ipv6 add)
inline explicit constexpr ip(ipv6 add) noexcept
: address{.address = {.v6 = add.address}}, port(add.port)
{}
inline explicit constexpr ip(ip_address addr, ::std::uint_least16_t prt)
inline explicit constexpr ip(ip_address addr, ::std::uint_least16_t prt) noexcept
: address{addr}, port{prt}
{}
};
Expand Down
21 changes: 11 additions & 10 deletions include/fast_io_hosted/platforms/win32/apis.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL SetWaitableTimer(void *, ::std::int_lea
FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL CancelWaitableTimer(void *) noexcept FAST_IO_WINSTDCALL_RENAME(CancelWaitableTimer, 4);
FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL LookupPrivilegeValueA(char const *__restrict, char const *__restrict, ::std::int_least64_t *) noexcept FAST_IO_WINSTDCALL_RENAME(LookupPrivilegeValueA, 12);
FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL LookupPrivilegeValueW(char16_t const *__restrict, char16_t const *__restrict, ::std::int_least64_t *) noexcept FAST_IO_WINSTDCALL_RENAME(LookupPrivilegeValueW, 12);
FAST_IO_DLLIMPORT void *FAST_IO_WINSTDCALL CreateThread(security_attributes *, ::std::size_t, ::std::uint_least32_t (FAST_IO_WINSTDCALL*)(void*), void*, ::std::uint_least32_t, ::std::uint_least32_t*) noexcept FAST_IO_WINSTDCALL_RENAME(CreateThread, 24);
FAST_IO_DLLIMPORT void *FAST_IO_WINSTDCALL CreateThread(security_attributes *, ::std::size_t, ::std::uint_least32_t(FAST_IO_WINSTDCALL *)(void *), void *, ::std::uint_least32_t, ::std::uint_least32_t *) noexcept FAST_IO_WINSTDCALL_RENAME(CreateThread, 24);
FAST_IO_DLLIMPORT char16_t **FAST_IO_WINSTDCALL CommandLineToArgvW(char16_t const *, int *) noexcept FAST_IO_WINSTDCALL_RENAME(CommandLineToArgvW, 8);
FAST_IO_DLLIMPORT void *FAST_IO_WINSTDCALL LocalFree(void *) noexcept FAST_IO_WINSTDCALL_RENAME(LocalFree, 4);
FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL PrefetchVirtualMemory(void *, ::std::size_t, ::fast_io::win32::win32_memory_range_entry *, ::std::uint_least32_t) noexcept FAST_IO_WINSTDCALL_RENAME(PrefetchVirtualMemory, 16);
Expand All @@ -182,16 +182,17 @@ FAST_IO_DLLIMPORT void FAST_IO_WINSTDCALL Sleep(::std::uint_least32_t) noexcept
FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL SwitchToThread() noexcept FAST_IO_WINSTDCALL_RENAME(SwitchToThread, 0);
FAST_IO_DLLIMPORT char16_t *FAST_IO_WINSTDCALL GetEnvironmentStringsW() noexcept FAST_IO_WINSTDCALL_RENAME(GetEnvironmentStringsW, 0);
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);
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);
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);
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);
FAST_IO_DLLIMPORT void FAST_IO_WINSTDCALL RaiseException(::std::uint_least32_t, ::std::uint_least32_t, ::std::uint_least32_t, ::std::size_t const *) noexcept FAST_IO_WINSTDCALL_RENAME(RaiseException, 16);
FAST_IO_DLLIMPORT void FAST_IO_WINSTDCALL ExitProcess(::std::uint_least32_t) noexcept FAST_IO_WINSTDCALL_RENAME(ExitProcess, 4);
FAST_IO_DLLIMPORT void *FAST_IO_WINSTDCALL AddVectoredExceptionHandler(::std::uint_least32_t, pvectored_exception_handler) noexcept FAST_IO_WINSTDCALL_RENAME(AddVectoredExceptionHandler, 8);

} // namespace fast_io::win32
42 changes: 42 additions & 0 deletions include/fast_io_hosted/platforms/win32/win32_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,4 +459,46 @@ struct win32_memory_range_entry
void* VirtualAddress;
::std::size_t NumberOfBytes;
};

inline constexpr ::std::size_t exception_maximum_parameters{15u};

struct exception_record
{
::std::uint_least32_t ExceptionCode;
::std::uint_least32_t ExceptionFlags;
exception_record* ExceptionRecord;
void* ExceptionAddress;
::std::uint_least32_t NumberParameters;
::std::size_t ExceptionInformation[exception_maximum_parameters];
};

struct exception_record32
{
::std::uint_least32_t ExceptionCode;
::std::uint_least32_t ExceptionFlags;
::std::uint_least32_t ExceptionRecord;
::std::uint_least32_t ExceptionAddress;
::std::uint_least32_t NumberParameters;
::std::uint_least32_t ExceptionInformation[exception_maximum_parameters];
};

struct exception_record64
{
::std::uint_least32_t ExceptionCode;
::std::uint_least32_t ExceptionFlags;
::std::uint_least64_t ExceptionRecord;
::std::uint_least64_t ExceptionAddress;
::std::uint_least32_t NumberParameters;
::std::uint_least32_t UnusedAlignment;
::std::uint_least64_t ExceptionInformation[exception_maximum_parameters];
};

struct exception_pointers
{
exception_record* ExceptionRecord;
void* ContextRecord;
};

using pvectored_exception_handler = ::std::int_least32_t(FAST_IO_WINSTDCALL *)(exception_pointers *) noexcept;

} // namespace fast_io::win32
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ struct win32_9xa_dns_iterator

inline constexpr win32_9xa_dns_iterator operator*(win32_9xa_dns_iterator d) noexcept
{
return {d.res};
return {d.res, d.pos};
}

inline constexpr win32_9xa_dns_iterator &operator++(win32_9xa_dns_iterator &d) noexcept
Expand Down Expand Up @@ -159,11 +159,16 @@ inline constexpr bool operator!=(win32_9xa_dns_iterator a, ::std::default_sentin
return !(a == b);
}

inline constexpr ::fast_io::ip to_ip(win32_9xa_dns_iterator d, ::std::uint_least16_t port)
inline constexpr ::fast_io::ip to_ip(win32_9xa_dns_iterator d, ::std::uint_least16_t port) noexcept
{
return ::fast_io::details::hostent_to_ip_impl(d.res, d.pos, port);
}

inline constexpr ::fast_io::ip_address to_ip_address(win32_9xa_dns_iterator d) noexcept
{
return ::fast_io::details::hostent_to_ip_address_impl(d.res, d.pos);
}

namespace details
{
inline ::fast_io::win32::hostent *win32_9xa_gethostbyname_impl(char const *name)
Expand Down
154 changes: 89 additions & 65 deletions include/fast_io_hosted/process/process/posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ namespace posix
// 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__)
#if (defined(__APPLE__) || defined(__DARWIN_C_LEVEL)) || (defined(__MSDOS__) || defined(__DJGPP__))
extern int libc_execve(char const *pathname, char *const *argv, char *const *envp) noexcept __asm__("_execve");
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");
extern int libc_kill(pid_t pid, int sig) noexcept __asm__("_kill");
Expand All @@ -24,6 +25,7 @@ extern pid_t libc_waitpid(pid_t pid, int *status, int options) noexcept __asm__(
[[noreturn]] extern void libc_exit(int status) noexcept __asm__("__Exit");
[[noreturn]] extern void libc_exit2(int status) noexcept __asm__("__exit");
#else
extern int libc_execve(char const *pathname, char *const *argv, char *const *envp) noexcept __asm__("execve");
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");
extern int libc_kill(pid_t pid, int sig) noexcept __asm__("kill");
Expand Down Expand Up @@ -403,20 +405,102 @@ inline void posix_waitpid_noexcept(pid_t pid) noexcept

inline int posix_execveat(int dirfd, char const *cstr, char const *const *args, char const *const *envp, process_mode mode) noexcept
{
bool const follow{(mode & process_mode::follow) == process_mode::follow};
[[maybe_unused]] bool const follow{(mode & process_mode::follow) == process_mode::follow};

#if defined(__linux__) && defined(__NR_execveat)
// linux execveat

int flags{};
if (!follow)
{
flags |= AT_SYMLINK_NOFOLLOW;
}
return -(system_call<__NR_execveat, int>(dirfd, cstr, args, envp, flags));

#elif defined(__APPLE__) || defined(__DARWIN_C_LEVEL)
// macOS / Darwin: no public execveat/fexecve
// Fallback: emulate execveat(dirfd, path, ...) using execve() and F_GETPATH.
// Limitations:
// - AT_SYMLINK_NOFOLLOW is ignored (no equivalent execve flag).
// - AT_EMPTY_PATH / other execveat-specific flags are not supported.

if (cstr == nullptr)
{
errno = EFAULT;
return errno;
}

#if defined(AT_FDCWD)
constexpr int fdcwd_val{AT_FDCWD};
#else
constexpr int fdcwd_val{-2};
#endif

// Absolute path: ignore dirfd, behave like execve()
if (cstr[0] == '/')
{
::fast_io::posix::libc_execve(cstr, const_cast<char *const *>(args), const_cast<char *const *>(envp));
return errno;
}

// Relative path and "current working directory" dirfd: just use execve()
if (dirfd == fdcwd_val)
{
::fast_io::posix::libc_execve(cstr, const_cast<char *const *>(args), const_cast<char *const *>(envp));
return errno;
}

// dirfd refers to a directory: resolve its absolute path via F_GETPATH and
// append the relative filename to form an absolute pathname.
#if defined(PATH_MAX)
constexpr ::std::size_t path_max{PATH_MAX};
#elif defined(MAXPATHLEN)
constexpr ::std::size_t path_max{MAXPATHLEN};
#else
constexpr ::std::size_t path_max{1024u};
#endif

constexpr ::std::size_t dirbuf_sz{path_max + 1u};

char dirbuf[dirbuf_sz]{};
auto ret_dir{::fast_io::details::posix::fcntl(dirfd, F_GETPATH, dirbuf)};
if (ret_dir == -1) [[unlikely]]
{
return errno;
}

auto dir_len{::fast_io::cstr_nlen(dirbuf, path_max)};
auto name_len{::fast_io::cstr_len(cstr)};

// Ensure combined path fits into our fixed buffer
if (dir_len + 1u + name_len >= path_max) [[unlikely]]
{
errno = ENAMETOOLONG;
return errno;
}

char fullpath[dirbuf_sz];
auto it{fullpath};
for (::std::size_t i{}; i < dir_len; ++i)
{
it[i] = dirbuf[i];
}
it[dir_len] = '/';
for (::std::size_t i{}; i < name_len; ++i)
{
it[dir_len + 1u + i] = cstr[i];
}
fullpath[dir_len + 1u + name_len] = '\0';

::fast_io::posix::libc_execve(fullpath, const_cast<char *const *>(args), const_cast<char *const *>(envp));
return errno;
#else
// POSIX 2008: openat + fexecve

int flags{O_RDONLY};
if (!follow)
{
flags |= AT_SYMLINK_NOFOLLOW;
flags |= O_NOFOLLOW;
}
int fd{::fast_io::details::my_posix_openat_noexcept(dirfd, cstr, flags, 0644)};
if (fd != -1) [[likely]]
Expand Down Expand Up @@ -716,7 +800,7 @@ struct fd_remapper
};

// only used in vfork_execveat_common_impl()
inline void vfork_and_execveat(pid_t &pid, int dirfd, char const *cstr, char const *const *args, char const *const *envp, unsigned volatile &t_errno, process_mode mode) noexcept
inline void vfork_and_execveat(pid_t &pid, int dirfd, char const *cstr, char const *const *args, char const *const *envp, unsigned volatile &t_errno, process_mode mode)
{
// vfork can only be called through libc wrapper
pid = ::fast_io::posix::libc_vfork();
Expand All @@ -741,68 +825,8 @@ inline void vfork_and_execveat(pid_t &pid, int dirfd, char const *cstr, char con
}
#endif

bool const follow{(mode & process_mode::follow) == process_mode::follow};

#if defined(__linux__)

#if defined(__NR_execveat)
int flags{};
if (!follow)
{
flags |= AT_SYMLINK_NOFOLLOW;
}

auto ret{system_call<__NR_execveat, int>(dirfd, cstr, args, envp, flags)};
if (::fast_io::linux_system_call_fails(ret))
{
t_errno = -ret;
}
else
{
t_errno = 0;
}
#else
int flags{};
if (!follow)
{
flags |= AT_SYMLINK_NOFOLLOW;
}

auto ret{::fast_io::posix::libc_execveat(dirfd, cstr, const_cast<char *const *>(args), const_cast<char *const *>(envp), flags)};
if (ret == -1)
{
t_errno = errno;
}
else
{
t_errno = 0;
}
#endif

#if defined(__NR_exit_group)
::fast_io::system_call_no_return<__NR_exit_group>(127);
#else
::fast_io::system_call_no_return<__NR_exit>(127);
#endif
#else
int flags{};
if (!follow)
{
flags |= AT_SYMLINK_NOFOLLOW;
}

auto ret{::fast_io::posix::libc_execveat(dirfd, cstr, const_cast<char *const *>(args), const_cast<char *const *>(envp), flags)};
if (ret == -1)
{
t_errno = errno;
}
else
{
t_errno = 0;
}

t_errno = posix_execveat(dirfd, cstr, args, envp, mode);
::fast_io::posix::libc_exit2(127);
#endif

__builtin_unreachable();
}
Expand Down
2 changes: 1 addition & 1 deletion include/fast_io_hosted/threads/thread/wasi.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#if defined(__wasi__)

Expand Down