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