1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 981ad6265SDimitry Andric #include <__config> 1081ad6265SDimitry Andric #ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS 1181ad6265SDimitry Andric # define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS 1281ad6265SDimitry Andric #endif 130b57cec5SDimitry Andric 1481ad6265SDimitry Andric #include <__assert> 15*fe013be4SDimitry Andric #include <__verbose_abort> 1681ad6265SDimitry Andric #include <cerrno> 1781ad6265SDimitry Andric #include <cstdio> 1881ad6265SDimitry Andric #include <cstdlib> 1981ad6265SDimitry Andric #include <cstring> 2081ad6265SDimitry Andric #include <string> 2181ad6265SDimitry Andric #include <string.h> 2281ad6265SDimitry Andric #include <system_error> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #include "include/config_elast.h" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #if defined(__ANDROID__) 270b57cec5SDimitry Andric #include <android/api-level.h> 280b57cec5SDimitry Andric #endif 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric // class error_category 330b57cec5SDimitry Andric 3481ad6265SDimitry Andric #if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS) 35fe6060f1SDimitry Andric error_category::error_category() noexcept 360b57cec5SDimitry Andric { 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric #endif 390b57cec5SDimitry Andric 40fe6060f1SDimitry Andric error_category::~error_category() noexcept 410b57cec5SDimitry Andric { 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric error_condition 45fe6060f1SDimitry Andric error_category::default_error_condition(int ev) const noexcept 460b57cec5SDimitry Andric { 470b57cec5SDimitry Andric return error_condition(ev, *this); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric bool 51fe6060f1SDimitry Andric error_category::equivalent(int code, const error_condition& condition) const noexcept 520b57cec5SDimitry Andric { 530b57cec5SDimitry Andric return default_error_condition(code) == condition; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric bool 57fe6060f1SDimitry Andric error_category::equivalent(const error_code& code, int condition) const noexcept 580b57cec5SDimitry Andric { 590b57cec5SDimitry Andric return *this == code.category() && code.value() == condition; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric #if !defined(_LIBCPP_HAS_NO_THREADS) 630b57cec5SDimitry Andric namespace { 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // GLIBC also uses 1024 as the maximum buffer size internally. 660b57cec5SDimitry Andric constexpr size_t strerror_buff_size = 1024; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric string do_strerror_r(int ev); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT_LIKE) 710b57cec5SDimitry Andric string do_strerror_r(int ev) { 720b57cec5SDimitry Andric char buffer[strerror_buff_size]; 730b57cec5SDimitry Andric if (::strerror_s(buffer, strerror_buff_size, ev) == 0) 740b57cec5SDimitry Andric return string(buffer); 750b57cec5SDimitry Andric std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev); 760b57cec5SDimitry Andric return string(buffer); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric #else 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // Only one of the two following functions will be used, depending on 810b57cec5SDimitry Andric // the return type of strerror_r: 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // For the GNU variant, a char* return value: 840b57cec5SDimitry Andric __attribute__((unused)) const char * 850b57cec5SDimitry Andric handle_strerror_r_return(char *strerror_return, char *buffer) { 860b57cec5SDimitry Andric // GNU always returns a string pointer in its return value. The 870b57cec5SDimitry Andric // string might point to either the input buffer, or a static 880b57cec5SDimitry Andric // buffer, but we don't care which. 890b57cec5SDimitry Andric return strerror_return; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // For the POSIX variant: an int return value. 930b57cec5SDimitry Andric __attribute__((unused)) const char * 940b57cec5SDimitry Andric handle_strerror_r_return(int strerror_return, char *buffer) { 950b57cec5SDimitry Andric // The POSIX variant either: 960b57cec5SDimitry Andric // - fills in the provided buffer and returns 0 970b57cec5SDimitry Andric // - returns a positive error value, or 980b57cec5SDimitry Andric // - returns -1 and fills in errno with an error value. 990b57cec5SDimitry Andric if (strerror_return == 0) 1000b57cec5SDimitry Andric return buffer; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Only handle EINVAL. Other errors abort. 1030b57cec5SDimitry Andric int new_errno = strerror_return == -1 ? errno : strerror_return; 1040b57cec5SDimitry Andric if (new_errno == EINVAL) 1050b57cec5SDimitry Andric return ""; 1060b57cec5SDimitry Andric 107*fe013be4SDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(new_errno == ERANGE, "unexpected error from ::strerror_r"); 1080b57cec5SDimitry Andric // FIXME maybe? 'strerror_buff_size' is likely to exceed the 1090b57cec5SDimitry Andric // maximum error size so ERANGE shouldn't be returned. 1100b57cec5SDimitry Andric std::abort(); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric // This function handles both GNU and POSIX variants, dispatching to 1140b57cec5SDimitry Andric // one of the two above functions. 1150b57cec5SDimitry Andric string do_strerror_r(int ev) { 1160b57cec5SDimitry Andric char buffer[strerror_buff_size]; 1170b57cec5SDimitry Andric // Preserve errno around the call. (The C++ standard requires that 1180b57cec5SDimitry Andric // system_error functions not modify errno). 1190b57cec5SDimitry Andric const int old_errno = errno; 1200b57cec5SDimitry Andric const char *error_message = handle_strerror_r_return( 1210b57cec5SDimitry Andric ::strerror_r(ev, buffer, strerror_buff_size), buffer); 1220b57cec5SDimitry Andric // If we didn't get any message, print one now. 1230b57cec5SDimitry Andric if (!error_message[0]) { 1240b57cec5SDimitry Andric std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev); 1250b57cec5SDimitry Andric error_message = buffer; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric errno = old_errno; 1280b57cec5SDimitry Andric return string(error_message); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric #endif 1310b57cec5SDimitry Andric } // end namespace 1320b57cec5SDimitry Andric #endif 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric string 1350b57cec5SDimitry Andric __do_message::message(int ev) const 1360b57cec5SDimitry Andric { 1370b57cec5SDimitry Andric #if defined(_LIBCPP_HAS_NO_THREADS) 1380b57cec5SDimitry Andric return string(::strerror(ev)); 1390b57cec5SDimitry Andric #else 1400b57cec5SDimitry Andric return do_strerror_r(ev); 1410b57cec5SDimitry Andric #endif 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric class _LIBCPP_HIDDEN __generic_error_category 1450b57cec5SDimitry Andric : public __do_message 1460b57cec5SDimitry Andric { 1470b57cec5SDimitry Andric public: 148fe6060f1SDimitry Andric virtual const char* name() const noexcept; 1490b57cec5SDimitry Andric virtual string message(int ev) const; 1500b57cec5SDimitry Andric }; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric const char* 153fe6060f1SDimitry Andric __generic_error_category::name() const noexcept 1540b57cec5SDimitry Andric { 1550b57cec5SDimitry Andric return "generic"; 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric string 1590b57cec5SDimitry Andric __generic_error_category::message(int ev) const 1600b57cec5SDimitry Andric { 1610b57cec5SDimitry Andric #ifdef _LIBCPP_ELAST 1620b57cec5SDimitry Andric if (ev > _LIBCPP_ELAST) 1630b57cec5SDimitry Andric return string("unspecified generic_category error"); 1640b57cec5SDimitry Andric #endif // _LIBCPP_ELAST 1650b57cec5SDimitry Andric return __do_message::message(ev); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric const error_category& 169fe6060f1SDimitry Andric generic_category() noexcept 1700b57cec5SDimitry Andric { 1710b57cec5SDimitry Andric static __generic_error_category s; 1720b57cec5SDimitry Andric return s; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric class _LIBCPP_HIDDEN __system_error_category 1760b57cec5SDimitry Andric : public __do_message 1770b57cec5SDimitry Andric { 1780b57cec5SDimitry Andric public: 179fe6060f1SDimitry Andric virtual const char* name() const noexcept; 1800b57cec5SDimitry Andric virtual string message(int ev) const; 181fe6060f1SDimitry Andric virtual error_condition default_error_condition(int ev) const noexcept; 1820b57cec5SDimitry Andric }; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric const char* 185fe6060f1SDimitry Andric __system_error_category::name() const noexcept 1860b57cec5SDimitry Andric { 1870b57cec5SDimitry Andric return "system"; 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric string 1910b57cec5SDimitry Andric __system_error_category::message(int ev) const 1920b57cec5SDimitry Andric { 1930b57cec5SDimitry Andric #ifdef _LIBCPP_ELAST 1940b57cec5SDimitry Andric if (ev > _LIBCPP_ELAST) 1950b57cec5SDimitry Andric return string("unspecified system_category error"); 1960b57cec5SDimitry Andric #endif // _LIBCPP_ELAST 1970b57cec5SDimitry Andric return __do_message::message(ev); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric error_condition 201fe6060f1SDimitry Andric __system_error_category::default_error_condition(int ev) const noexcept 2020b57cec5SDimitry Andric { 2030b57cec5SDimitry Andric #ifdef _LIBCPP_ELAST 2040b57cec5SDimitry Andric if (ev > _LIBCPP_ELAST) 2050b57cec5SDimitry Andric return error_condition(ev, system_category()); 2060b57cec5SDimitry Andric #endif // _LIBCPP_ELAST 2070b57cec5SDimitry Andric return error_condition(ev, generic_category()); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric const error_category& 211fe6060f1SDimitry Andric system_category() noexcept 2120b57cec5SDimitry Andric { 2130b57cec5SDimitry Andric static __system_error_category s; 2140b57cec5SDimitry Andric return s; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric // error_condition 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric string 2200b57cec5SDimitry Andric error_condition::message() const 2210b57cec5SDimitry Andric { 2220b57cec5SDimitry Andric return __cat_->message(__val_); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric // error_code 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric string 2280b57cec5SDimitry Andric error_code::message() const 2290b57cec5SDimitry Andric { 2300b57cec5SDimitry Andric return __cat_->message(__val_); 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric // system_error 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric string 2360b57cec5SDimitry Andric system_error::__init(const error_code& ec, string what_arg) 2370b57cec5SDimitry Andric { 2380b57cec5SDimitry Andric if (ec) 2390b57cec5SDimitry Andric { 2400b57cec5SDimitry Andric if (!what_arg.empty()) 2410b57cec5SDimitry Andric what_arg += ": "; 2420b57cec5SDimitry Andric what_arg += ec.message(); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric return what_arg; 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric system_error::system_error(error_code ec, const string& what_arg) 2480b57cec5SDimitry Andric : runtime_error(__init(ec, what_arg)), 2490b57cec5SDimitry Andric __ec_(ec) 2500b57cec5SDimitry Andric { 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric system_error::system_error(error_code ec, const char* what_arg) 2540b57cec5SDimitry Andric : runtime_error(__init(ec, what_arg)), 2550b57cec5SDimitry Andric __ec_(ec) 2560b57cec5SDimitry Andric { 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric system_error::system_error(error_code ec) 2600b57cec5SDimitry Andric : runtime_error(__init(ec, "")), 2610b57cec5SDimitry Andric __ec_(ec) 2620b57cec5SDimitry Andric { 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric system_error::system_error(int ev, const error_category& ecat, const string& what_arg) 2660b57cec5SDimitry Andric : runtime_error(__init(error_code(ev, ecat), what_arg)), 2670b57cec5SDimitry Andric __ec_(error_code(ev, ecat)) 2680b57cec5SDimitry Andric { 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric system_error::system_error(int ev, const error_category& ecat, const char* what_arg) 2720b57cec5SDimitry Andric : runtime_error(__init(error_code(ev, ecat), what_arg)), 2730b57cec5SDimitry Andric __ec_(error_code(ev, ecat)) 2740b57cec5SDimitry Andric { 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric system_error::system_error(int ev, const error_category& ecat) 2780b57cec5SDimitry Andric : runtime_error(__init(error_code(ev, ecat), "")), 2790b57cec5SDimitry Andric __ec_(error_code(ev, ecat)) 2800b57cec5SDimitry Andric { 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 283fe6060f1SDimitry Andric system_error::~system_error() noexcept 2840b57cec5SDimitry Andric { 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric void 2880b57cec5SDimitry Andric __throw_system_error(int ev, const char* what_arg) 2890b57cec5SDimitry Andric { 290*fe013be4SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2910b57cec5SDimitry Andric throw system_error(error_code(ev, system_category()), what_arg); 2920b57cec5SDimitry Andric #else 293*fe013be4SDimitry Andric _LIBCPP_VERBOSE_ABORT("system_error was thrown in -fno-exceptions mode with error %i and message \"%s\"", ev, what_arg); 2940b57cec5SDimitry Andric #endif 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 298