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 int ret; 74 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) { 75 // If `ret == -1` then the error is specified using `errno`, otherwise 76 // `ret` represents the error. 77 const int new_errno = ret == -1 ? errno : ret; 78 errno = old_errno; 79 if (new_errno == EINVAL) { 80 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev); 81 return string(buffer); 82 } else { 83 assert(new_errno == ERANGE); 84 // FIXME maybe? 'strerror_buff_size' is likely to exceed the 85 // maximum error size so ERANGE shouldn't be returned. 86 std::abort(); 87 } 88 } 89 return string(buffer); 90 } 91 #endif 92 93 } // end namespace 94 95 string 96 __do_message::message(int ev) const 97 { 98 #if defined(_LIBCPP_HAS_NO_THREADS) 99 return string(::strerror(ev)); 100 #else 101 return do_strerror_r(ev); 102 #endif 103 } 104 105 class _LIBCPP_HIDDEN __generic_error_category 106 : public __do_message 107 { 108 public: 109 virtual const char* name() const _NOEXCEPT; 110 virtual string message(int ev) const; 111 }; 112 113 const char* 114 __generic_error_category::name() const _NOEXCEPT 115 { 116 return "generic"; 117 } 118 119 string 120 __generic_error_category::message(int ev) const 121 { 122 #ifdef _LIBCPP_ELAST 123 if (ev > _LIBCPP_ELAST) 124 return string("unspecified generic_category error"); 125 #endif // _LIBCPP_ELAST 126 return __do_message::message(ev); 127 } 128 129 const error_category& 130 generic_category() _NOEXCEPT 131 { 132 static __generic_error_category s; 133 return s; 134 } 135 136 class _LIBCPP_HIDDEN __system_error_category 137 : public __do_message 138 { 139 public: 140 virtual const char* name() const _NOEXCEPT; 141 virtual string message(int ev) const; 142 virtual error_condition default_error_condition(int ev) const _NOEXCEPT; 143 }; 144 145 const char* 146 __system_error_category::name() const _NOEXCEPT 147 { 148 return "system"; 149 } 150 151 string 152 __system_error_category::message(int ev) const 153 { 154 #ifdef _LIBCPP_ELAST 155 if (ev > _LIBCPP_ELAST) 156 return string("unspecified system_category error"); 157 #endif // _LIBCPP_ELAST 158 return __do_message::message(ev); 159 } 160 161 error_condition 162 __system_error_category::default_error_condition(int ev) const _NOEXCEPT 163 { 164 #ifdef _LIBCPP_ELAST 165 if (ev > _LIBCPP_ELAST) 166 return error_condition(ev, system_category()); 167 #endif // _LIBCPP_ELAST 168 return error_condition(ev, generic_category()); 169 } 170 171 const error_category& 172 system_category() _NOEXCEPT 173 { 174 static __system_error_category s; 175 return s; 176 } 177 178 // error_condition 179 180 string 181 error_condition::message() const 182 { 183 return __cat_->message(__val_); 184 } 185 186 // error_code 187 188 string 189 error_code::message() const 190 { 191 return __cat_->message(__val_); 192 } 193 194 // system_error 195 196 string 197 system_error::__init(const error_code& ec, string what_arg) 198 { 199 if (ec) 200 { 201 if (!what_arg.empty()) 202 what_arg += ": "; 203 what_arg += ec.message(); 204 } 205 return what_arg; 206 } 207 208 system_error::system_error(error_code ec, const string& what_arg) 209 : runtime_error(__init(ec, what_arg)), 210 __ec_(ec) 211 { 212 } 213 214 system_error::system_error(error_code ec, const char* what_arg) 215 : runtime_error(__init(ec, what_arg)), 216 __ec_(ec) 217 { 218 } 219 220 system_error::system_error(error_code ec) 221 : runtime_error(__init(ec, "")), 222 __ec_(ec) 223 { 224 } 225 226 system_error::system_error(int ev, const error_category& ecat, const string& what_arg) 227 : runtime_error(__init(error_code(ev, ecat), what_arg)), 228 __ec_(error_code(ev, ecat)) 229 { 230 } 231 232 system_error::system_error(int ev, const error_category& ecat, const char* what_arg) 233 : runtime_error(__init(error_code(ev, ecat), what_arg)), 234 __ec_(error_code(ev, ecat)) 235 { 236 } 237 238 system_error::system_error(int ev, const error_category& ecat) 239 : runtime_error(__init(error_code(ev, ecat), "")), 240 __ec_(error_code(ev, ecat)) 241 { 242 } 243 244 system_error::~system_error() _NOEXCEPT 245 { 246 } 247 248 void 249 __throw_system_error(int ev, const char* what_arg) 250 { 251 #ifndef _LIBCPP_NO_EXCEPTIONS 252 throw system_error(error_code(ev, system_category()), what_arg); 253 #else 254 (void)ev; 255 (void)what_arg; 256 #endif 257 } 258 259 _LIBCPP_END_NAMESPACE_STD 260