xref: /openbsd-src/gnu/llvm/libcxx/src/system_error.cpp (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
1*4bdff4beSrobert //===----------------------------------------------------------------------===//
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===//
846035553Spatrick 
9*4bdff4beSrobert #include <__config>
10*4bdff4beSrobert #ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
11*4bdff4beSrobert #   define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS
12*4bdff4beSrobert #endif
1346035553Spatrick 
14*4bdff4beSrobert #include <__assert>
15*4bdff4beSrobert #include <cerrno>
16*4bdff4beSrobert #include <cstdio>
17*4bdff4beSrobert #include <cstdlib>
18*4bdff4beSrobert #include <cstring>
19*4bdff4beSrobert #include <string>
20*4bdff4beSrobert #include <string.h>
21*4bdff4beSrobert #include <system_error>
2246035553Spatrick 
2346035553Spatrick #include "include/config_elast.h"
2446035553Spatrick 
2546035553Spatrick #if defined(__ANDROID__)
2646035553Spatrick #include <android/api-level.h>
2746035553Spatrick #endif
2846035553Spatrick 
2946035553Spatrick _LIBCPP_BEGIN_NAMESPACE_STD
3046035553Spatrick 
3146035553Spatrick // class error_category
3246035553Spatrick 
33*4bdff4beSrobert #if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS)
error_category()3476d0caaeSpatrick error_category::error_category() noexcept
3546035553Spatrick {
3646035553Spatrick }
3746035553Spatrick #endif
3846035553Spatrick 
~error_category()3976d0caaeSpatrick error_category::~error_category() noexcept
4046035553Spatrick {
4146035553Spatrick }
4246035553Spatrick 
4346035553Spatrick error_condition
default_error_condition(int ev) const4476d0caaeSpatrick error_category::default_error_condition(int ev) const noexcept
4546035553Spatrick {
4646035553Spatrick     return error_condition(ev, *this);
4746035553Spatrick }
4846035553Spatrick 
4946035553Spatrick bool
equivalent(int code,const error_condition & condition) const5076d0caaeSpatrick error_category::equivalent(int code, const error_condition& condition) const noexcept
5146035553Spatrick {
5246035553Spatrick     return default_error_condition(code) == condition;
5346035553Spatrick }
5446035553Spatrick 
5546035553Spatrick bool
equivalent(const error_code & code,int condition) const5676d0caaeSpatrick error_category::equivalent(const error_code& code, int condition) const noexcept
5746035553Spatrick {
5846035553Spatrick     return *this == code.category() && code.value() == condition;
5946035553Spatrick }
6046035553Spatrick 
6146035553Spatrick #if !defined(_LIBCPP_HAS_NO_THREADS)
6246035553Spatrick namespace {
6346035553Spatrick 
6446035553Spatrick //  GLIBC also uses 1024 as the maximum buffer size internally.
6546035553Spatrick constexpr size_t strerror_buff_size = 1024;
6646035553Spatrick 
6746035553Spatrick string do_strerror_r(int ev);
6846035553Spatrick 
6946035553Spatrick #if defined(_LIBCPP_MSVCRT_LIKE)
do_strerror_r(int ev)7046035553Spatrick string do_strerror_r(int ev) {
7146035553Spatrick   char buffer[strerror_buff_size];
7246035553Spatrick   if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
7346035553Spatrick     return string(buffer);
7446035553Spatrick   std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
7546035553Spatrick   return string(buffer);
7646035553Spatrick }
7746035553Spatrick #else
7846035553Spatrick 
7946035553Spatrick // Only one of the two following functions will be used, depending on
8046035553Spatrick // the return type of strerror_r:
8146035553Spatrick 
8246035553Spatrick // For the GNU variant, a char* return value:
8346035553Spatrick __attribute__((unused)) const char *
handle_strerror_r_return(char * strerror_return,char * buffer)8446035553Spatrick handle_strerror_r_return(char *strerror_return, char *buffer) {
8546035553Spatrick   // GNU always returns a string pointer in its return value. The
8646035553Spatrick   // string might point to either the input buffer, or a static
8746035553Spatrick   // buffer, but we don't care which.
8846035553Spatrick   return strerror_return;
8946035553Spatrick }
9046035553Spatrick 
9146035553Spatrick // For the POSIX variant: an int return value.
9246035553Spatrick __attribute__((unused)) const char *
handle_strerror_r_return(int strerror_return,char * buffer)9346035553Spatrick handle_strerror_r_return(int strerror_return, char *buffer) {
9446035553Spatrick   // The POSIX variant either:
9546035553Spatrick   // - fills in the provided buffer and returns 0
9646035553Spatrick   // - returns a positive error value, or
9746035553Spatrick   // - returns -1 and fills in errno with an error value.
9846035553Spatrick   if (strerror_return == 0)
9946035553Spatrick     return buffer;
10046035553Spatrick 
10146035553Spatrick   // Only handle EINVAL. Other errors abort.
10246035553Spatrick   int new_errno = strerror_return == -1 ? errno : strerror_return;
10346035553Spatrick   if (new_errno == EINVAL)
10446035553Spatrick     return "";
10546035553Spatrick 
10646035553Spatrick   _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
10746035553Spatrick   // FIXME maybe? 'strerror_buff_size' is likely to exceed the
10846035553Spatrick   // maximum error size so ERANGE shouldn't be returned.
10946035553Spatrick   std::abort();
11046035553Spatrick }
11146035553Spatrick 
11246035553Spatrick // This function handles both GNU and POSIX variants, dispatching to
11346035553Spatrick // one of the two above functions.
do_strerror_r(int ev)11446035553Spatrick string do_strerror_r(int ev) {
11546035553Spatrick     char buffer[strerror_buff_size];
11646035553Spatrick     // Preserve errno around the call. (The C++ standard requires that
11746035553Spatrick     // system_error functions not modify errno).
11846035553Spatrick     const int old_errno = errno;
11946035553Spatrick     const char *error_message = handle_strerror_r_return(
12046035553Spatrick         ::strerror_r(ev, buffer, strerror_buff_size), buffer);
12146035553Spatrick     // If we didn't get any message, print one now.
12246035553Spatrick     if (!error_message[0]) {
12346035553Spatrick       std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
12446035553Spatrick       error_message = buffer;
12546035553Spatrick     }
12646035553Spatrick     errno = old_errno;
12746035553Spatrick     return string(error_message);
12846035553Spatrick }
12946035553Spatrick #endif
13046035553Spatrick } // end namespace
13146035553Spatrick #endif
13246035553Spatrick 
13346035553Spatrick string
message(int ev) const13446035553Spatrick __do_message::message(int ev) const
13546035553Spatrick {
13646035553Spatrick #if defined(_LIBCPP_HAS_NO_THREADS)
13746035553Spatrick     return string(::strerror(ev));
13846035553Spatrick #else
13946035553Spatrick     return do_strerror_r(ev);
14046035553Spatrick #endif
14146035553Spatrick }
14246035553Spatrick 
14346035553Spatrick class _LIBCPP_HIDDEN __generic_error_category
14446035553Spatrick     : public __do_message
14546035553Spatrick {
14646035553Spatrick public:
14776d0caaeSpatrick     virtual const char* name() const noexcept;
14846035553Spatrick     virtual string message(int ev) const;
14946035553Spatrick };
15046035553Spatrick 
15146035553Spatrick const char*
name() const15276d0caaeSpatrick __generic_error_category::name() const noexcept
15346035553Spatrick {
15446035553Spatrick     return "generic";
15546035553Spatrick }
15646035553Spatrick 
15746035553Spatrick string
message(int ev) const15846035553Spatrick __generic_error_category::message(int ev) const
15946035553Spatrick {
16046035553Spatrick #ifdef _LIBCPP_ELAST
16146035553Spatrick     if (ev > _LIBCPP_ELAST)
16246035553Spatrick       return string("unspecified generic_category error");
16346035553Spatrick #endif // _LIBCPP_ELAST
16446035553Spatrick     return __do_message::message(ev);
16546035553Spatrick }
16646035553Spatrick 
16746035553Spatrick const error_category&
generic_category()16876d0caaeSpatrick generic_category() noexcept
16946035553Spatrick {
17046035553Spatrick     static __generic_error_category s;
17146035553Spatrick     return s;
17246035553Spatrick }
17346035553Spatrick 
17446035553Spatrick class _LIBCPP_HIDDEN __system_error_category
17546035553Spatrick     : public __do_message
17646035553Spatrick {
17746035553Spatrick public:
17876d0caaeSpatrick     virtual const char* name() const noexcept;
17946035553Spatrick     virtual string message(int ev) const;
18076d0caaeSpatrick     virtual error_condition default_error_condition(int ev) const noexcept;
18146035553Spatrick };
18246035553Spatrick 
18346035553Spatrick const char*
name() const18476d0caaeSpatrick __system_error_category::name() const noexcept
18546035553Spatrick {
18646035553Spatrick     return "system";
18746035553Spatrick }
18846035553Spatrick 
18946035553Spatrick string
message(int ev) const19046035553Spatrick __system_error_category::message(int ev) const
19146035553Spatrick {
19246035553Spatrick #ifdef _LIBCPP_ELAST
19346035553Spatrick     if (ev > _LIBCPP_ELAST)
19446035553Spatrick       return string("unspecified system_category error");
19546035553Spatrick #endif // _LIBCPP_ELAST
19646035553Spatrick     return __do_message::message(ev);
19746035553Spatrick }
19846035553Spatrick 
19946035553Spatrick error_condition
default_error_condition(int ev) const20076d0caaeSpatrick __system_error_category::default_error_condition(int ev) const noexcept
20146035553Spatrick {
20246035553Spatrick #ifdef _LIBCPP_ELAST
20346035553Spatrick     if (ev > _LIBCPP_ELAST)
20446035553Spatrick       return error_condition(ev, system_category());
20546035553Spatrick #endif // _LIBCPP_ELAST
20646035553Spatrick     return error_condition(ev, generic_category());
20746035553Spatrick }
20846035553Spatrick 
20946035553Spatrick const error_category&
system_category()21076d0caaeSpatrick system_category() noexcept
21146035553Spatrick {
21246035553Spatrick     static __system_error_category s;
21346035553Spatrick     return s;
21446035553Spatrick }
21546035553Spatrick 
21646035553Spatrick // error_condition
21746035553Spatrick 
21846035553Spatrick string
message() const21946035553Spatrick error_condition::message() const
22046035553Spatrick {
22146035553Spatrick     return __cat_->message(__val_);
22246035553Spatrick }
22346035553Spatrick 
22446035553Spatrick // error_code
22546035553Spatrick 
22646035553Spatrick string
message() const22746035553Spatrick error_code::message() const
22846035553Spatrick {
22946035553Spatrick     return __cat_->message(__val_);
23046035553Spatrick }
23146035553Spatrick 
23246035553Spatrick // system_error
23346035553Spatrick 
23446035553Spatrick string
__init(const error_code & ec,string what_arg)23546035553Spatrick system_error::__init(const error_code& ec, string what_arg)
23646035553Spatrick {
23746035553Spatrick     if (ec)
23846035553Spatrick     {
23946035553Spatrick         if (!what_arg.empty())
24046035553Spatrick             what_arg += ": ";
24146035553Spatrick         what_arg += ec.message();
24246035553Spatrick     }
24346035553Spatrick     return what_arg;
24446035553Spatrick }
24546035553Spatrick 
system_error(error_code ec,const string & what_arg)24646035553Spatrick system_error::system_error(error_code ec, const string& what_arg)
24746035553Spatrick     : runtime_error(__init(ec, what_arg)),
24846035553Spatrick       __ec_(ec)
24946035553Spatrick {
25046035553Spatrick }
25146035553Spatrick 
system_error(error_code ec,const char * what_arg)25246035553Spatrick system_error::system_error(error_code ec, const char* what_arg)
25346035553Spatrick     : runtime_error(__init(ec, what_arg)),
25446035553Spatrick       __ec_(ec)
25546035553Spatrick {
25646035553Spatrick }
25746035553Spatrick 
system_error(error_code ec)25846035553Spatrick system_error::system_error(error_code ec)
25946035553Spatrick     : runtime_error(__init(ec, "")),
26046035553Spatrick       __ec_(ec)
26146035553Spatrick {
26246035553Spatrick }
26346035553Spatrick 
system_error(int ev,const error_category & ecat,const string & what_arg)26446035553Spatrick system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
26546035553Spatrick     : runtime_error(__init(error_code(ev, ecat), what_arg)),
26646035553Spatrick       __ec_(error_code(ev, ecat))
26746035553Spatrick {
26846035553Spatrick }
26946035553Spatrick 
system_error(int ev,const error_category & ecat,const char * what_arg)27046035553Spatrick system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
27146035553Spatrick     : runtime_error(__init(error_code(ev, ecat), what_arg)),
27246035553Spatrick       __ec_(error_code(ev, ecat))
27346035553Spatrick {
27446035553Spatrick }
27546035553Spatrick 
system_error(int ev,const error_category & ecat)27646035553Spatrick system_error::system_error(int ev, const error_category& ecat)
27746035553Spatrick     : runtime_error(__init(error_code(ev, ecat), "")),
27846035553Spatrick       __ec_(error_code(ev, ecat))
27946035553Spatrick {
28046035553Spatrick }
28146035553Spatrick 
~system_error()28276d0caaeSpatrick system_error::~system_error() noexcept
28346035553Spatrick {
28446035553Spatrick }
28546035553Spatrick 
28646035553Spatrick void
__throw_system_error(int ev,const char * what_arg)28746035553Spatrick __throw_system_error(int ev, const char* what_arg)
28846035553Spatrick {
28946035553Spatrick #ifndef _LIBCPP_NO_EXCEPTIONS
29046035553Spatrick     throw system_error(error_code(ev, system_category()), what_arg);
29146035553Spatrick #else
29246035553Spatrick     (void)ev;
29346035553Spatrick     (void)what_arg;
29446035553Spatrick     _VSTD::abort();
29546035553Spatrick #endif
29646035553Spatrick }
29746035553Spatrick 
29846035553Spatrick _LIBCPP_END_NAMESPACE_STD
299