system_error.cc revision 1.1.1.12
1// <system_error> implementation file 2 3// Copyright (C) 2007-2022 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25 26#define _GLIBCXX_USE_CXX11_ABI 1 27#define __sso_string __sso_stringxxx 28#include <cstring> 29#include <system_error> 30#include <bits/functexcept.h> 31#include <limits> 32#include <errno.h> 33#undef __sso_string 34 35#if defined(_WIN32) && !defined(__CYGWIN__) 36#include <memory> 37#include <windows.h> 38#endif 39 40#if __has_cpp_attribute(clang::require_constant_initialization) 41# define __constinit [[clang::require_constant_initialization]] 42#endif 43 44namespace 45{ 46 using std::string; 47 48 template<typename T> 49 struct constant_init 50 { 51 union { 52 unsigned char unused; 53 T obj; 54 }; 55 constexpr constant_init() : obj() { } 56 57 ~constant_init() { /* do nothing, union member is not destroyed */ } 58 }; 59 60 struct generic_error_category final : public std::error_category 61 { 62 const char* 63 name() const noexcept final 64 { return "generic"; } 65 66 _GLIBCXX_DEFAULT_ABI_TAG 67 string 68 message(int i) const final 69 { 70 // XXX locale issues: how does one get or set loc. 71 // _GLIBCXX_HAVE_STRERROR_L, strerror_l(i, cloc) 72 return string(strerror(i)); 73 } 74 75 // Override this to avoid a virtual call to default_error_condition(i). 76 bool 77 equivalent(int i, const std::error_condition& cond) const noexcept final 78 { return i == cond.value() && *this == cond.category(); } 79 }; 80 81 __constinit constant_init<generic_error_category> generic_category_instance{}; 82 83 struct system_error_category final : public std::error_category 84 { 85 const char* 86 name() const noexcept final 87 { return "system"; } 88 89 _GLIBCXX_DEFAULT_ABI_TAG 90 string 91 message(int i) const final 92 { 93#if defined(_WIN32) && !defined(__CYGWIN__) 94 char* buf = nullptr; 95 auto len 96 = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 97 | FORMAT_MESSAGE_ALLOCATE_BUFFER, 98 nullptr, 99 i, 100 LANG_USER_DEFAULT, 101 reinterpret_cast<LPTSTR>(&buf), 102 0, 103 nullptr); 104 if (len > 0) 105 { 106 struct deleter { 107 void operator()(void* p) const { ::LocalFree(p); } 108 }; 109 std::unique_ptr<char[], deleter> guard(buf); 110 if (len > 3 && !__builtin_memcmp(buf + len - 3, ".\r\n", 3)) [[likely]] 111 len -= 3; 112 return string(buf, len); 113 } 114 return string("Unknown error code"); 115#else 116 // XXX locale issues: how does one get or set loc. 117 // _GLIBCXX_HAVE_STRERROR_L, strerror_l(i, cloc) 118 return string(strerror(i)); 119#endif 120 } 121 122 std::error_condition 123 default_error_condition(int ev) const noexcept final 124 { 125 // Use generic category for all known POSIX errno values (including zero) 126 // and system category otherwise. 127 switch (ev) 128 { 129#if defined(_WIN32) && !defined(__CYGWIN__) 130 case 0: 131 return {0, generic_category_instance.obj}; 132 // Convert Windows error code into a corresponding POSIX errno value. 133#define X(w, e) case ERROR_##w: return {e, generic_category_instance.obj}; 134 // This list is based on Cygwin's winsup/cygwin/errno.cc 135 X (ACCESS_DENIED, EACCES); 136 X (ACTIVE_CONNECTIONS, EAGAIN); 137 X (ALREADY_EXISTS, EEXIST); 138 X (BAD_DEVICE, ENODEV); 139 X (BAD_EXE_FORMAT, ENOEXEC); 140 X (BAD_NETPATH, ENOENT); 141 X (BAD_NET_NAME, ENOENT); 142 X (BAD_NET_RESP, ENOSYS); 143 X (BAD_PATHNAME, ENOENT); 144 X (BAD_PIPE, EINVAL); 145 X (BAD_UNIT, ENODEV); 146 X (BAD_USERNAME, EINVAL); 147 X (BEGINNING_OF_MEDIA, EIO); 148 X (BROKEN_PIPE, EPIPE); 149 X (BUSY, EBUSY); 150 X (BUS_RESET, EIO); 151 X (CALL_NOT_IMPLEMENTED, ENOSYS); 152 X (CANCELLED, EINTR); 153 X (CANNOT_MAKE, EPERM); 154 X (CHILD_NOT_COMPLETE, EBUSY); 155 X (COMMITMENT_LIMIT, EAGAIN); 156 X (CONNECTION_REFUSED, ECONNREFUSED); 157 X (CRC, EIO); 158 X (DEVICE_DOOR_OPEN, EIO); 159 X (DEVICE_IN_USE, EAGAIN); 160 X (DEVICE_REQUIRES_CLEANING, EIO); 161 X (DEV_NOT_EXIST, ENOENT); 162 X (DIRECTORY, ENOTDIR); 163 X (DIR_NOT_EMPTY, ENOTEMPTY); 164 X (DISK_CORRUPT, EIO); 165#ifdef ENOSPC 166 X (DISK_FULL, ENOSPC); 167#endif 168 X (DS_GENERIC_ERROR, EIO); 169#ifdef ENOSPC 170 X (END_OF_MEDIA, ENOSPC); 171#endif 172 X (EOM_OVERFLOW, EIO); 173 X (EXE_MACHINE_TYPE_MISMATCH, ENOEXEC); 174 X (EXE_MARKED_INVALID, ENOEXEC); 175 X (FILEMARK_DETECTED, EIO); 176 X (FILENAME_EXCED_RANGE, ENAMETOOLONG); 177 X (FILE_CORRUPT, EEXIST); 178 X (FILE_EXISTS, EEXIST); 179 X (FILE_INVALID, ENXIO); 180 X (FILE_NOT_FOUND, ENOENT); 181#ifdef ENOSPC 182 X (HANDLE_DISK_FULL, ENOSPC); 183#endif 184 X (INVALID_ADDRESS, EINVAL); 185 X (INVALID_AT_INTERRUPT_TIME, EINTR); 186 X (INVALID_BLOCK_LENGTH, EIO); 187 X (INVALID_DATA, EINVAL); 188 X (INVALID_DRIVE, ENODEV); 189 X (INVALID_EA_NAME, EINVAL); 190 X (INVALID_EXE_SIGNATURE, ENOEXEC); 191 X (INVALID_HANDLE, EBADF); 192 X (INVALID_NAME, ENOENT); 193 X (INVALID_PARAMETER, EINVAL); 194 X (INVALID_SIGNAL_NUMBER, EINVAL); 195 X (IOPL_NOT_ENABLED, ENOEXEC); 196 X (IO_DEVICE, EIO); 197 X (IO_INCOMPLETE, EAGAIN); 198 X (IO_PENDING, EAGAIN); 199 X (LOCK_VIOLATION, EBUSY); 200 X (MAX_THRDS_REACHED, EAGAIN); 201 X (META_EXPANSION_TOO_LONG, EINVAL); 202 X (MOD_NOT_FOUND, ENOENT); 203 X (MORE_DATA, EMSGSIZE); 204 X (NEGATIVE_SEEK, EINVAL); 205 X (NETNAME_DELETED, ENOENT); 206 X (NOACCESS, EFAULT); 207 X (NONE_MAPPED, EINVAL); 208 X (NONPAGED_SYSTEM_RESOURCES, EAGAIN); 209 X (NOT_ENOUGH_MEMORY, ENOMEM); 210 X (NOT_ENOUGH_QUOTA, EIO); 211#ifdef EPERM 212 X (NOT_OWNER, EPERM); 213#else 214 X (NOT_OWNER, EACCES); 215#endif 216 X (NOT_SAME_DEVICE, EXDEV); 217 X (NOT_SUPPORTED, ENOSYS); 218 X (NO_DATA, EPIPE); 219 X (NO_DATA_DETECTED, EIO); 220 X (NO_MORE_SEARCH_HANDLES, ENFILE); 221 X (NO_PROC_SLOTS, EAGAIN); 222 X (NO_SIGNAL_SENT, EIO); 223 X (NO_SYSTEM_RESOURCES, EFBIG); 224 X (NO_TOKEN, EINVAL); 225 X (OPEN_FAILED, EIO); 226 X (OPEN_FILES, EAGAIN); 227 X (OUTOFMEMORY, ENOMEM); 228 X (PAGED_SYSTEM_RESOURCES, EAGAIN); 229 X (PAGEFILE_QUOTA, EAGAIN); 230 X (PATH_NOT_FOUND, ENOENT); 231 X (PIPE_BUSY, EBUSY); 232 X (PIPE_CONNECTED, EBUSY); 233 X (POSSIBLE_DEADLOCK, EDEADLK); 234 X (PRIVILEGE_NOT_HELD, EPERM); 235 X (PROCESS_ABORTED, EFAULT); 236 X (PROC_NOT_FOUND, ESRCH); 237 X (SECTOR_NOT_FOUND, EINVAL); 238 X (SEEK, EINVAL); 239 X (SERVICE_REQUEST_TIMEOUT, EBUSY); 240 X (SETMARK_DETECTED, EIO); 241 X (SHARING_BUFFER_EXCEEDED, ENOLCK); 242 X (SHARING_VIOLATION, EBUSY); 243 X (SIGNAL_PENDING, EBUSY); 244 X (SIGNAL_REFUSED, EIO); 245 X (THREAD_1_INACTIVE, EINVAL); 246 X (TIMEOUT, EBUSY); 247 X (TOO_MANY_LINKS, EMLINK); 248 X (TOO_MANY_OPEN_FILES, EMFILE); 249 X (UNEXP_NET_ERR, EIO); 250 X (WORKING_SET_QUOTA, EAGAIN); 251 X (WRITE_PROTECT, EROFS); 252#undef X 253 254#elif defined __AVR__ 255 // avr-libc only defines a few distinct error numbers. Most <errno.h> 256 // constants are not usable in #if directives and have the same value. 257 case EDOM: 258 case ERANGE: 259 case ENOSYS: 260 case EINTR: 261 case 0: 262 return std::error_condition(ev, generic_category_instance.obj); 263#else 264 // List of errno macros from [cerrno.syn]. 265 // C11 only defines EDOM, EILSEQ and ERANGE, the rest are from POSIX. 266 // They expand to integer constant expressions with type int, 267 // and distinct positive values, suitable for use in #if directives. 268 // POSIX adds more macros (but they're not defined on all targets, 269 // see config/os/.../error_constants.h), and POSIX allows 270 // EAGAIN == EWOULDBLOCK and ENOTSUP == EOPNOTSUPP. 271 272#ifdef E2BIG 273 case E2BIG: 274#endif 275#ifdef EACCES 276 case EACCES: 277#endif 278#ifdef EADDRINUSE 279 case EADDRINUSE: 280#endif 281#ifdef EADDRNOTAVAIL 282 case EADDRNOTAVAIL: 283#endif 284#ifdef EAFNOSUPPORT 285 case EAFNOSUPPORT: 286#endif 287#ifdef EAGAIN 288 case EAGAIN: 289#endif 290#ifdef EALREADY 291 case EALREADY: 292#endif 293#ifdef EBADF 294 case EBADF: 295#endif 296#ifdef EBADMSG 297 case EBADMSG: 298#endif 299#ifdef EBUSY 300 case EBUSY: 301#endif 302#ifdef ECANCELED 303 case ECANCELED: 304#endif 305#ifdef ECHILD 306 case ECHILD: 307#endif 308#ifdef ECONNABORTED 309 case ECONNABORTED: 310#endif 311#ifdef ECONNREFUSED 312 case ECONNREFUSED: 313#endif 314#ifdef ECONNRESET 315 case ECONNRESET: 316#endif 317#ifdef EDEADLK 318 case EDEADLK: 319#endif 320#ifdef EDESTADDRREQ 321 case EDESTADDRREQ: 322#endif 323 case EDOM: 324#ifdef EEXIST 325 case EEXIST: 326#endif 327#ifdef EFAULT 328 case EFAULT: 329#endif 330#ifdef EFBIG 331 case EFBIG: 332#endif 333#ifdef EHOSTUNREACH 334 case EHOSTUNREACH: 335#endif 336#ifdef EIDRM 337 case EIDRM: 338#endif 339 case EILSEQ: 340#ifdef EINPROGRESS 341 case EINPROGRESS: 342#endif 343#ifdef EINTR 344 case EINTR: 345#endif 346#ifdef EINVAL 347 case EINVAL: 348#endif 349#ifdef EIO 350 case EIO: 351#endif 352#ifdef EISCONN 353 case EISCONN: 354#endif 355#ifdef EISDIR 356 case EISDIR: 357#endif 358#ifdef ELOOP 359 case ELOOP: 360#endif 361#ifdef EMFILE 362 case EMFILE: 363#endif 364#ifdef EMLINK 365 case EMLINK: 366#endif 367#ifdef EMSGSIZE 368 case EMSGSIZE: 369#endif 370#ifdef ENAMETOOLONG 371 case ENAMETOOLONG: 372#endif 373#ifdef ENETDOWN 374 case ENETDOWN: 375#endif 376#ifdef ENETRESET 377 case ENETRESET: 378#endif 379#ifdef ENETUNREACH 380 case ENETUNREACH: 381#endif 382#ifdef ENFILE 383 case ENFILE: 384#endif 385#ifdef ENOBUFS 386 case ENOBUFS: 387#endif 388#ifdef ENODATA 389 case ENODATA: 390#endif 391#ifdef ENODEV 392 case ENODEV: 393#endif 394#ifdef ENOENT 395 case ENOENT: 396#endif 397#ifdef ENOEXEC 398 case ENOEXEC: 399#endif 400#ifdef ENOLCK 401 case ENOLCK: 402#endif 403#ifdef ENOLINK 404 case ENOLINK: 405#endif 406#ifdef ENOMEM 407 case ENOMEM: 408#endif 409#ifdef ENOMSG 410 case ENOMSG: 411#endif 412#ifdef ENOPROTOOPT 413 case ENOPROTOOPT: 414#endif 415#ifdef ENOSPC 416 case ENOSPC: 417#endif 418#ifdef ENOSR 419 case ENOSR: 420#endif 421#ifdef ENOSTR 422 case ENOSTR: 423#endif 424#ifdef ENOSYS 425 case ENOSYS: 426#endif 427#ifdef ENOTCONN 428 case ENOTCONN: 429#endif 430#ifdef ENOTDIR 431 case ENOTDIR: 432#endif 433#if defined ENOTEMPTY && (!defined EEXIST || ENOTEMPTY != EEXIST) 434 // AIX sometimes uses the same value for EEXIST and ENOTEMPTY 435 case ENOTEMPTY: 436#endif 437#ifdef ENOTRECOVERABLE 438 case ENOTRECOVERABLE: 439#endif 440#ifdef ENOTSOCK 441 case ENOTSOCK: 442#endif 443#if defined ENOTSUP && (!defined ENOSYS || ENOTSUP != ENOSYS) 444 // zTPF uses the same value for ENOSYS and ENOTSUP 445 case ENOTSUP: 446#endif 447#ifdef ENOTTY 448 case ENOTTY: 449#endif 450#ifdef ENXIO 451 case ENXIO: 452#endif 453#if defined EOPNOTSUPP && (!defined ENOTSUP || EOPNOTSUPP != ENOTSUP) 454 case EOPNOTSUPP: 455#endif 456#ifdef EOVERFLOW 457 case EOVERFLOW: 458#endif 459#ifdef EOWNERDEAD 460 case EOWNERDEAD: 461#endif 462#ifdef EPERM 463 case EPERM: 464#endif 465#ifdef EPIPE 466 case EPIPE: 467#endif 468#ifdef EPROTO 469 case EPROTO: 470#endif 471#ifdef EPROTONOSUPPORT 472 case EPROTONOSUPPORT: 473#endif 474#ifdef EPROTOTYPE 475 case EPROTOTYPE: 476#endif 477 case ERANGE: 478#ifdef EROFS 479 case EROFS: 480#endif 481#ifdef ESPIPE 482 case ESPIPE: 483#endif 484#ifdef ESRCH 485 case ESRCH: 486#endif 487#ifdef ETIME 488 case ETIME: 489#endif 490#ifdef ETIMEDOUT 491 case ETIMEDOUT: 492#endif 493#ifdef ETXTBSY 494 case ETXTBSY: 495#endif 496#if defined EWOULDBLOCK && (!defined EAGAIN || EWOULDBLOCK != EAGAIN) 497 case EWOULDBLOCK: 498#endif 499#ifdef EXDEV 500 case EXDEV: 501#endif 502 case 0: 503 return std::error_condition(ev, generic_category_instance.obj); 504 505 /* Additional system-dependent mappings from non-standard error codes 506 * to one of the POSIX values above would go here, e.g. 507 case EBLAH: 508 return std::error_condition(EINVAL, std::generic_category()); 509 */ 510 511#endif 512 default: 513 return std::error_condition(ev, *this); 514 } 515 } 516 517 // Override this to avoid a virtual call to default_error_condition(i). 518 bool 519 equivalent(int i, const std::error_condition& cond) const noexcept final 520 { return system_error_category::default_error_condition(i) == cond; } 521 }; 522 523 __constinit constant_init<system_error_category> system_category_instance{}; 524} 525 526namespace std _GLIBCXX_VISIBILITY(default) 527{ 528_GLIBCXX_BEGIN_NAMESPACE_VERSION 529 530 void 531 __throw_system_error(int __i __attribute__((unused))) 532 { 533 _GLIBCXX_THROW_OR_ABORT(system_error(__i, generic_category_instance.obj)); 534 } 535 536 error_category::~error_category() = default; 537 538 const error_category& 539 _V2::system_category() noexcept { return system_category_instance.obj; } 540 541 const error_category& 542 _V2::generic_category() noexcept { return generic_category_instance.obj; } 543 544 system_error::~system_error() = default; 545 546 error_condition 547 error_category::default_error_condition(int __i) const noexcept 548 { return error_condition(__i, *this); } 549 550 bool 551 error_category::equivalent(int __i, 552 const error_condition& __cond) const noexcept 553 { return default_error_condition(__i) == __cond; } 554 555 bool 556 error_category::equivalent(const error_code& __code, int __i) const noexcept 557 { return *this == __code.category() && __code.value() == __i; } 558 559 error_condition 560 error_code::default_error_condition() const noexcept 561 { return category().default_error_condition(value()); } 562 563#if _GLIBCXX_USE_CXX11_ABI 564 // Return error_category::message() as a COW string 565 __cow_string 566 error_category::_M_message(int i) const 567 { 568 string msg = this->message(i); 569 return {msg.c_str(), msg.length()}; 570 } 571#endif 572 573_GLIBCXX_END_NAMESPACE_VERSION 574} // namespace 575