From 2c4b88753b46001477e48c80dae09a846a9d7d34 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Thu, 25 Jul 2024 01:05:39 -0700 Subject: [PATCH] Add special errno handling to libcxx --- libc/integral/normalize.inc | 4 - third_party/libcxx/BUILD.mk | 1 + third_party/libcxx/README.cosmo | 2 +- third_party/libcxx/__system_error/errc.h | 2 +- third_party/libcxx/config_elast.h | 2 +- third_party/libcxx/fs/cosmo.cpp | 188 +++++++++++++++++++ third_party/libcxx/fs/directory_iterator.cpp | 8 + third_party/libcxx/fs/error.h | 7 + third_party/libcxx/fs/file_descriptor.h | 5 + third_party/libcxx/system_error.cpp | 23 +++ 10 files changed, 235 insertions(+), 7 deletions(-) create mode 100644 third_party/libcxx/fs/cosmo.cpp diff --git a/libc/integral/normalize.inc b/libc/integral/normalize.inc index 6dc68490ff9..5093ec96989 100644 --- a/libc/integral/normalize.inc +++ b/libc/integral/normalize.inc @@ -83,10 +83,6 @@ #define __BIGGEST_ALIGNMENT__ 16 #endif -#ifdef _COSMO_SOURCE -#define _PAGESIZE 4096 -#endif - #if defined(__LP64__) && !defined(__INT64_TYPE__) #include "libc/integral/lp64.inc" #elif defined(_MSC_VER) && !defined(__INT64_TYPE__) diff --git a/third_party/libcxx/BUILD.mk b/third_party/libcxx/BUILD.mk index a7d25568c06..22c4a0d840f 100644 --- a/third_party/libcxx/BUILD.mk +++ b/third_party/libcxx/BUILD.mk @@ -1094,6 +1094,7 @@ third_party/libcxx/fs/filesystem_clock.cpp \ third_party/libcxx/fs/filesystem_error.cpp \ third_party/libcxx/fs/int128_builtins.cpp \ third_party/libcxx/fs/operations.cpp \ +third_party/libcxx/fs/cosmo.cpp \ third_party/libcxx/fs/path.cpp \ third_party/libcxx/ryu/d2fixed.cpp \ third_party/libcxx/ryu/d2s.cpp \ diff --git a/third_party/libcxx/README.cosmo b/third_party/libcxx/README.cosmo index 7a86bd50559..1aebb72c99d 100644 --- a/third_party/libcxx/README.cosmo +++ b/third_party/libcxx/README.cosmo @@ -11,5 +11,5 @@ ORIGIN LOCAL CHANGES - Wrote __config_site + - Add special handling for cosmo errno - Shaped and molded directory structure - - Kludged (and probably broke) awful `cerr` feature diff --git a/third_party/libcxx/__system_error/errc.h b/third_party/libcxx/__system_error/errc.h index 7086530eb6e..33a2645d920 100644 --- a/third_party/libcxx/__system_error/errc.h +++ b/third_party/libcxx/__system_error/errc.h @@ -141,7 +141,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // This leads to the odd pushing and popping of the deprecated // diagnostic. _LIBCPP_DECLARE_STRONG_ENUM(errc){ - address_family_not_supported, // = EAFNOSUPPORT, + address_family_not_supported = 65536, // = EAFNOSUPPORT, address_in_use, // = EADDRINUSE, address_not_available, // = EADDRNOTAVAIL, already_connected, // = EISCONN, diff --git a/third_party/libcxx/config_elast.h b/third_party/libcxx/config_elast.h index 06f0d042b89..d47a53f2ed3 100644 --- a/third_party/libcxx/config_elast.h +++ b/third_party/libcxx/config_elast.h @@ -32,7 +32,7 @@ #elif defined(__EMSCRIPTEN__) // No _LIBCPP_ELAST needed on Emscripten #elif defined(__COSMOPOLITAN__) -#define _LIBCPP_ELAST 65535 +// No _LIBCPP_ELAST needed on Cosmopolitan #elif defined(__linux__) || defined(_LIBCPP_HAS_MUSL_LIBC) #define _LIBCPP_ELAST 4095 #elif defined(__APPLE__) diff --git a/third_party/libcxx/fs/cosmo.cpp b/third_party/libcxx/fs/cosmo.cpp new file mode 100644 index 00000000000..fbb2ab1d41f --- /dev/null +++ b/third_party/libcxx/fs/cosmo.cpp @@ -0,0 +1,188 @@ +#ifdef __COSMOPOLITAN__ +#include + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { + +std::errc __cosmo_err_to_errc_impl(int err) { + if (err == EAFNOSUPPORT) return errc::address_family_not_supported; + if (err == EADDRINUSE) return errc::address_in_use; + if (err == EADDRNOTAVAIL) return errc::address_not_available; + if (err == EISCONN) return errc::already_connected; + if (err == E2BIG) return errc::argument_list_too_long; + if (err == EDOM) return errc::argument_out_of_domain; + if (err == EFAULT) return errc::bad_address; + if (err == EBADF) return errc::bad_file_descriptor; + if (err == EBADMSG) return errc::bad_message; + if (err == EPIPE) return errc::broken_pipe; + if (err == ECONNABORTED) return errc::connection_aborted; + if (err == EALREADY) return errc::connection_already_in_progress; + if (err == ECONNREFUSED) return errc::connection_refused; + if (err == ECONNRESET) return errc::connection_reset; + if (err == EXDEV) return errc::cross_device_link; + if (err == EDESTADDRREQ) return errc::destination_address_required; + if (err == EBUSY) return errc::device_or_resource_busy; + if (err == ENOTEMPTY) return errc::directory_not_empty; + if (err == ENOEXEC) return errc::executable_format_error; + if (err == EEXIST) return errc::file_exists; + if (err == EFBIG) return errc::file_too_large; + if (err == ENAMETOOLONG) return errc::filename_too_long; + if (err == ENOSYS) return errc::function_not_supported; + if (err == EHOSTUNREACH) return errc::host_unreachable; + if (err == EIDRM) return errc::identifier_removed; + if (err == EILSEQ) return errc::illegal_byte_sequence; + if (err == ENOTTY) return errc::inappropriate_io_control_operation; + if (err == EINTR) return errc::interrupted; + if (err == EINVAL) return errc::invalid_argument; + if (err == ESPIPE) return errc::invalid_seek; + if (err == EIO) return errc::io_error; + if (err == EISDIR) return errc::is_a_directory; + if (err == EMSGSIZE) return errc::message_size; + if (err == ENETDOWN) return errc::network_down; + if (err == ENETRESET) return errc::network_reset; + if (err == ENETUNREACH) return errc::network_unreachable; + if (err == ENOBUFS) return errc::no_buffer_space; + if (err == ECHILD) return errc::no_child_process; + if (err == ENOLINK) return errc::no_link; + if (err == ENOLCK) return errc::no_lock_available; + if (err == ENOMSG) return errc::no_message; + if (err == (ENODATA ? ENODATA : ENOMSG)) return errc::no_message_available; + if (err == ENOPROTOOPT) return errc::no_protocol_option; + if (err == ENOSPC) return errc::no_space_on_device; + if (err == ENOMEM) return errc::not_enough_memory; + if (err == (ENOSR ? ENOSR : ENOMEM)) return errc::no_stream_resources; + if (err == ENXIO) return errc::no_such_device_or_address; + if (err == ENODEV) return errc::no_such_device; + if (err == ENOENT) return errc::no_such_file_or_directory; + if (err == ESRCH) return errc::no_such_process; + if (err == ENOTDIR) return errc::not_a_directory; + if (err == ENOTSOCK) return errc::not_a_socket; + if (err == (ENOSTR ? ENOSTR : EINVAL)) return errc::not_a_stream; + if (err == ENOTCONN) return errc::not_connected; + if (err == ENOTSUP) return errc::not_supported; + if (err == ECANCELED) return errc::operation_canceled; + if (err == EINPROGRESS) return errc::operation_in_progress; + if (err == EPERM) return errc::operation_not_permitted; + if (err == EOPNOTSUPP) return errc::operation_not_supported; + if (err == EWOULDBLOCK) return errc::operation_would_block; + if (err == EOWNERDEAD) return errc::owner_dead; + if (err == EACCES) return errc::permission_denied; + if (err == EPROTO) return errc::protocol_error; + if (err == EPROTONOSUPPORT) return errc::protocol_not_supported; + if (err == EROFS) return errc::read_only_file_system; + if (err == EDEADLK) return errc::resource_deadlock_would_occur; + if (err == EAGAIN) return errc::resource_unavailable_try_again; + if (err == ERANGE) return errc::result_out_of_range; + if (err == ENOTRECOVERABLE) return errc::state_not_recoverable; + if (err == ETIME) return errc::stream_timeout; + if (err == ETXTBSY) return errc::text_file_busy; + if (err == ETIMEDOUT) return errc::timed_out; + if (err == ENFILE) return errc::too_many_files_open_in_system; + if (err == EMFILE) return errc::too_many_files_open; + if (err == EMLINK) return errc::too_many_links; + if (err == ELOOP) return errc::too_many_symbolic_link_levels; + if (err == EOVERFLOW) return errc::value_too_large; + if (err == EPROTOTYPE) return errc::wrong_protocol_type; + return errc::not_supported; +} + +int __cosmo_errc_to_err_impl(std::errc err) { + if (err == errc::address_family_not_supported) return EAFNOSUPPORT; + if (err == errc::address_in_use) return EADDRINUSE; + if (err == errc::address_not_available) return EADDRNOTAVAIL; + if (err == errc::already_connected) return EISCONN; + if (err == errc::argument_list_too_long) return E2BIG; + if (err == errc::argument_out_of_domain) return EDOM; + if (err == errc::bad_address) return EFAULT; + if (err == errc::bad_file_descriptor) return EBADF; + if (err == errc::bad_message) return EBADMSG; + if (err == errc::broken_pipe) return EPIPE; + if (err == errc::connection_aborted) return ECONNABORTED; + if (err == errc::connection_already_in_progress) return EALREADY; + if (err == errc::connection_refused) return ECONNREFUSED; + if (err == errc::connection_reset) return ECONNRESET; + if (err == errc::cross_device_link) return EXDEV; + if (err == errc::destination_address_required) return EDESTADDRREQ; + if (err == errc::device_or_resource_busy) return EBUSY; + if (err == errc::directory_not_empty) return ENOTEMPTY; + if (err == errc::executable_format_error) return ENOEXEC; + if (err == errc::file_exists) return EEXIST; + if (err == errc::file_too_large) return EFBIG; + if (err == errc::filename_too_long) return ENAMETOOLONG; + if (err == errc::function_not_supported) return ENOSYS; + if (err == errc::host_unreachable) return EHOSTUNREACH; + if (err == errc::identifier_removed) return EIDRM; + if (err == errc::illegal_byte_sequence) return EILSEQ; + if (err == errc::inappropriate_io_control_operation) return ENOTTY; + if (err == errc::interrupted) return EINTR; + if (err == errc::invalid_argument) return EINVAL; + if (err == errc::invalid_seek) return ESPIPE; + if (err == errc::io_error) return EIO; + if (err == errc::is_a_directory) return EISDIR; + if (err == errc::message_size) return EMSGSIZE; + if (err == errc::network_down) return ENETDOWN; + if (err == errc::network_reset) return ENETRESET; + if (err == errc::network_unreachable) return ENETUNREACH; + if (err == errc::no_buffer_space) return ENOBUFS; + if (err == errc::no_child_process) return ECHILD; + if (err == errc::no_link) return ENOLINK; + if (err == errc::no_lock_available) return ENOLCK; + if (err == errc::no_message) return ENOMSG; + if (err == errc::no_message_available) return (ENODATA ? ENODATA : ENOMSG); + if (err == errc::no_protocol_option) return ENOPROTOOPT; + if (err == errc::no_space_on_device) return ENOSPC; + if (err == errc::not_enough_memory) return ENOMEM; + if (err == errc::no_stream_resources) return (ENOSR ? ENOSR : ENOMEM); + if (err == errc::no_such_device_or_address) return ENXIO; + if (err == errc::no_such_device) return ENODEV; + if (err == errc::no_such_file_or_directory) return ENOENT; + if (err == errc::no_such_process) return ESRCH; + if (err == errc::not_a_directory) return ENOTDIR; + if (err == errc::not_a_socket) return ENOTSOCK; + if (err == errc::not_a_stream) return (ENOSTR ? ENOSTR : EINVAL); + if (err == errc::not_connected) return ENOTCONN; + if (err == errc::not_supported) return ENOTSUP; + if (err == errc::operation_canceled) return ECANCELED; + if (err == errc::operation_in_progress) return EINPROGRESS; + if (err == errc::operation_not_permitted) return EPERM; + if (err == errc::operation_not_supported) return EOPNOTSUPP; + if (err == errc::operation_would_block) return EWOULDBLOCK; + if (err == errc::owner_dead) return EOWNERDEAD; + if (err == errc::permission_denied) return EACCES; + if (err == errc::protocol_error) return EPROTO; + if (err == errc::protocol_not_supported) return EPROTONOSUPPORT; + if (err == errc::read_only_file_system) return EROFS; + if (err == errc::resource_deadlock_would_occur) return EDEADLK; + if (err == errc::resource_unavailable_try_again) return EAGAIN; + if (err == errc::result_out_of_range) return ERANGE; + if (err == errc::state_not_recoverable) return ENOTRECOVERABLE; + if (err == errc::stream_timeout) return ETIME; + if (err == errc::text_file_busy) return ETXTBSY; + if (err == errc::timed_out) return ETIMEDOUT; + if (err == errc::too_many_files_open_in_system) return ENFILE; + if (err == errc::too_many_files_open) return EMFILE; + if (err == errc::too_many_links) return EMLINK; + if (err == errc::too_many_symbolic_link_levels) return ELOOP; + if (err == errc::value_too_large) return EOVERFLOW; + if (err == errc::wrong_protocol_type) return EPROTOTYPE; + return ENOTSUP; +} + +std::errc __cosmo_err_to_errc(int err) { + if (err >= 65536) + return (std::errc)err; + return __cosmo_err_to_errc_impl(err); +} + +int __cosmo_errc_to_err(std::errc err) { + if ((int)err < 65536) + return (int)err; + return __cosmo_errc_to_err_impl(err); +} + +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // __COSMOPOLITAN__ diff --git a/third_party/libcxx/fs/directory_iterator.cpp b/third_party/libcxx/fs/directory_iterator.cpp index dceb3486279..a7ffa91889f 100644 --- a/third_party/libcxx/fs/directory_iterator.cpp +++ b/third_party/libcxx/fs/directory_iterator.cpp @@ -118,7 +118,11 @@ class __dir_stream { if ((__stream_ = ::opendir(root.c_str())) == nullptr) { ec = detail::capture_errno(); const bool allow_eacces = bool(opts & directory_options::skip_permission_denied); +#ifdef __COSMOPOLITAN__ + if (allow_eacces && ec.value() == (int)errc::permission_denied) +#else if (allow_eacces && ec.value() == EACCES) +#endif ec.clear(); return; } @@ -307,7 +311,11 @@ bool recursive_directory_iterator::__try_recursion(error_code* ec) { } if (m_ec) { const bool allow_eacess = bool(__imp_->__options_ & directory_options::skip_permission_denied); +#ifdef __COSMOPOLITAN__ + if (m_ec.value() == (int)errc::permission_denied && allow_eacess) { +#else if (m_ec.value() == EACCES && allow_eacess) { +#endif if (ec) ec->clear(); } else { diff --git a/third_party/libcxx/fs/error.h b/third_party/libcxx/fs/error.h index 572cc73292a..e74d0691766 100644 --- a/third_party/libcxx/fs/error.h +++ b/third_party/libcxx/fs/error.h @@ -98,9 +98,16 @@ inline errc __win_err_to_errc(int err) { #endif // _LIBCPP_WIN32API +errc __cosmo_err_to_errc(int); +int __cosmo_errc_to_err(errc); + inline error_code capture_errno() { _LIBCPP_ASSERT_INTERNAL(errno != 0, "Expected errno to be non-zero"); +#ifdef __COSMOPOLITAN__ + return error_code((int)__cosmo_err_to_errc(errno), generic_category()); +#else return error_code(errno, generic_category()); +#endif } #if defined(_LIBCPP_WIN32API) diff --git a/third_party/libcxx/fs/file_descriptor.h b/third_party/libcxx/fs/file_descriptor.h index 50178ff84e0..d41fe77bb38 100644 --- a/third_party/libcxx/fs/file_descriptor.h +++ b/third_party/libcxx/fs/file_descriptor.h @@ -194,7 +194,12 @@ inline perms posix_get_perms(const StatT& st) noexcept { return static_cast err("posix_stat", ec, &p); diff --git a/third_party/libcxx/system_error.cpp b/third_party/libcxx/system_error.cpp index 482e51ee654..6f6b417a9f1 100644 --- a/third_party/libcxx/system_error.cpp +++ b/third_party/libcxx/system_error.cpp @@ -23,6 +23,10 @@ # include #endif +#ifdef __COSMOPOLITAN__ +#include +#endif + _LIBCPP_BEGIN_NAMESPACE_STD namespace { @@ -35,6 +39,9 @@ string do_strerror_r(int ev); # if defined(_LIBCPP_MSVCRT_LIKE) string do_strerror_r(int ev) { +#ifdef __COSMOPOLITAN__ + ev = (int)filesystem::detail::__cosmo_errc_to_err(ev); +#endif char buffer[strerror_buff_size]; if (::strerror_s(buffer, strerror_buff_size, ev) == 0) return string(buffer); @@ -81,6 +88,9 @@ string do_strerror_r(int ev) { // Preserve errno around the call. (The C++ standard requires that // system_error functions not modify errno). const int old_errno = errno; +#ifdef __COSMOPOLITAN__ + ev = filesystem::detail::__cosmo_errc_to_err((errc)ev); +#endif const char* error_message = handle_strerror_r_return(::strerror_r(ev, buffer, strerror_buff_size), buffer); // If we didn't get any message, print one now. if (!error_message[0]) { @@ -129,6 +139,9 @@ class _LIBCPP_HIDDEN __generic_error_category : public __do_message { const char* __generic_error_category::name() const noexcept { return "generic"; } string __generic_error_category::message(int ev) const { +#ifdef __COSMOPOLITAN__ + ev = filesystem::detail::__cosmo_errc_to_err((errc)ev); +#endif #ifdef _LIBCPP_ELAST if (ev > _LIBCPP_ELAST) return string("unspecified generic_category error"); @@ -156,6 +169,9 @@ class _LIBCPP_HIDDEN __system_error_category : public __do_message { const char* __system_error_category::name() const noexcept { return "system"; } string __system_error_category::message(int ev) const { +#ifdef __COSMOPOLITAN__ + ev = filesystem::detail::__cosmo_errc_to_err((errc)ev); +#endif #ifdef _LIBCPP_ELAST if (ev > _LIBCPP_ELAST) return string("unspecified system_category error"); @@ -164,6 +180,9 @@ string __system_error_category::message(int ev) const { } error_condition __system_error_category::default_error_condition(int ev) const noexcept { +#ifdef __COSMOPOLITAN__ + ev = filesystem::detail::__cosmo_errc_to_err((errc)ev); +#endif #ifdef _LIBCPP_ELAST if (ev > _LIBCPP_ELAST) return error_condition(ev, system_category()); @@ -212,7 +231,11 @@ system_error::~system_error() noexcept {} void __throw_system_error(int ev, const char* what_arg) { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS +#ifdef __COSMOPOLITAN__ + std::__throw_system_error(error_code((int)filesystem::detail::__cosmo_err_to_errc(ev), system_category()), what_arg); +#else std::__throw_system_error(error_code(ev, system_category()), what_arg); +#endif #else // The above could also handle the no-exception case, but for size, avoid referencing system_category() unnecessarily. _LIBCPP_VERBOSE_ABORT(