1//===---------------------- system_error.cpp ------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "__config" 11 12#define _LIBCPP_BUILDING_SYSTEM_ERROR 13#include "system_error" 14 15#include "include/config_elast.h" 16#include "cerrno" 17#include "cstring" 18#include "cstdio" 19#include "cstdlib" 20#include "string" 21#include "string.h" 22#include "__debug" 23 24#if defined(__ANDROID__) 25#include <android/api-level.h> 26#endif 27 28_LIBCPP_BEGIN_NAMESPACE_STD 29 30// class error_category 31 32#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) 33error_category::error_category() _NOEXCEPT 34{ 35} 36#endif 37 38error_category::~error_category() _NOEXCEPT 39{ 40} 41 42error_condition 43error_category::default_error_condition(int ev) const _NOEXCEPT 44{ 45 return error_condition(ev, *this); 46} 47 48bool 49error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT 50{ 51 return default_error_condition(code) == condition; 52} 53 54bool 55error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT 56{ 57 return *this == code.category() && code.value() == condition; 58} 59 60#if !defined(_LIBCPP_HAS_NO_THREADS) 61namespace { 62 63// GLIBC also uses 1024 as the maximum buffer size internally. 64constexpr size_t strerror_buff_size = 1024; 65 66string do_strerror_r(int ev); 67 68#if defined(_LIBCPP_MSVCRT) 69string do_strerror_r(int ev) { 70 char buffer[strerror_buff_size]; 71 if (::strerror_s(buffer, strerror_buff_size, ev) == 0) 72 return string(buffer); 73 std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev); 74 return string(buffer); 75} 76#elif defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) && \ 77 (!defined(__ANDROID__) || __ANDROID_API__ >= 23) 78// GNU Extended version 79string do_strerror_r(int ev) { 80 char buffer[strerror_buff_size]; 81 char* ret = ::strerror_r(ev, buffer, strerror_buff_size); 82 return string(ret); 83} 84#else 85// POSIX version 86string do_strerror_r(int ev) { 87 char buffer[strerror_buff_size]; 88 const int old_errno = errno; 89 int ret; 90 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) { 91 // If `ret == -1` then the error is specified using `errno`, otherwise 92 // `ret` represents the error. 93 const int new_errno = ret == -1 ? errno : ret; 94 errno = old_errno; 95 if (new_errno == EINVAL) { 96 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev); 97 return string(buffer); 98 } else { 99 _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerr_r"); 100 // FIXME maybe? 'strerror_buff_size' is likely to exceed the 101 // maximum error size so ERANGE shouldn't be returned. 102 std::abort(); 103 } 104 } 105 return string(buffer); 106} 107#endif 108 109} // end namespace 110#endif 111 112string 113__do_message::message(int ev) const 114{ 115#if defined(_LIBCPP_HAS_NO_THREADS) 116 return string(::strerror(ev)); 117#else 118 return do_strerror_r(ev); 119#endif 120} 121 122class _LIBCPP_HIDDEN __generic_error_category 123 : public __do_message 124{ 125public: 126 virtual const char* name() const _NOEXCEPT; 127 virtual string message(int ev) const; 128}; 129 130const char* 131__generic_error_category::name() const _NOEXCEPT 132{ 133 return "generic"; 134} 135 136string 137__generic_error_category::message(int ev) const 138{ 139#ifdef _LIBCPP_ELAST 140 if (ev > _LIBCPP_ELAST) 141 return string("unspecified generic_category error"); 142#endif // _LIBCPP_ELAST 143 return __do_message::message(ev); 144} 145 146const error_category& 147generic_category() _NOEXCEPT 148{ 149 static __generic_error_category s; 150 return s; 151} 152 153class _LIBCPP_HIDDEN __system_error_category 154 : public __do_message 155{ 156public: 157 virtual const char* name() const _NOEXCEPT; 158 virtual string message(int ev) const; 159 virtual error_condition default_error_condition(int ev) const _NOEXCEPT; 160}; 161 162const char* 163__system_error_category::name() const _NOEXCEPT 164{ 165 return "system"; 166} 167 168string 169__system_error_category::message(int ev) const 170{ 171#ifdef _LIBCPP_ELAST 172 if (ev > _LIBCPP_ELAST) 173 return string("unspecified system_category error"); 174#endif // _LIBCPP_ELAST 175 return __do_message::message(ev); 176} 177 178error_condition 179__system_error_category::default_error_condition(int ev) const _NOEXCEPT 180{ 181#ifdef _LIBCPP_ELAST 182 if (ev > _LIBCPP_ELAST) 183 return error_condition(ev, system_category()); 184#endif // _LIBCPP_ELAST 185 return error_condition(ev, generic_category()); 186} 187 188const error_category& 189system_category() _NOEXCEPT 190{ 191 static __system_error_category s; 192 return s; 193} 194 195// error_condition 196 197string 198error_condition::message() const 199{ 200 return __cat_->message(__val_); 201} 202 203// error_code 204 205string 206error_code::message() const 207{ 208 return __cat_->message(__val_); 209} 210 211// system_error 212 213string 214system_error::__init(const error_code& ec, string what_arg) 215{ 216 if (ec) 217 { 218 if (!what_arg.empty()) 219 what_arg += ": "; 220 what_arg += ec.message(); 221 } 222 return what_arg; 223} 224 225system_error::system_error(error_code ec, const string& what_arg) 226 : runtime_error(__init(ec, what_arg)), 227 __ec_(ec) 228{ 229} 230 231system_error::system_error(error_code ec, const char* what_arg) 232 : runtime_error(__init(ec, what_arg)), 233 __ec_(ec) 234{ 235} 236 237system_error::system_error(error_code ec) 238 : runtime_error(__init(ec, "")), 239 __ec_(ec) 240{ 241} 242 243system_error::system_error(int ev, const error_category& ecat, const string& what_arg) 244 : runtime_error(__init(error_code(ev, ecat), what_arg)), 245 __ec_(error_code(ev, ecat)) 246{ 247} 248 249system_error::system_error(int ev, const error_category& ecat, const char* what_arg) 250 : runtime_error(__init(error_code(ev, ecat), what_arg)), 251 __ec_(error_code(ev, ecat)) 252{ 253} 254 255system_error::system_error(int ev, const error_category& ecat) 256 : runtime_error(__init(error_code(ev, ecat), "")), 257 __ec_(error_code(ev, ecat)) 258{ 259} 260 261system_error::~system_error() _NOEXCEPT 262{ 263} 264 265void 266__throw_system_error(int ev, const char* what_arg) 267{ 268#ifndef _LIBCPP_NO_EXCEPTIONS 269 throw system_error(error_code(ev, system_category()), what_arg); 270#else 271 (void)ev; 272 (void)what_arg; 273 _VSTD::abort(); 274#endif 275} 276 277_LIBCPP_END_NAMESPACE_STD 278