libstdc++: Use strerror_r in std::generic_category()::message(int) [PR110133]
[official-gcc.git] / libstdc++-v3 / src / c++11 / system_error.cc
blob876e2bb44fc45439d546da8e326edf8bed0bf261
1 // <system_error> implementation file
3 // Copyright (C) 2007-2023 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.
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.
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.
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/>.
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
35 #if defined(_WIN32) && !defined(__CYGWIN__)
36 #define WIN32_LEAN_AND_MEAN
37 #include <memory>
38 #include <windows.h>
39 #endif
41 #if __has_cpp_attribute(clang::require_constant_initialization)
42 # define __constinit [[clang::require_constant_initialization]]
43 #endif
45 namespace
47 using std::string;
49 #if _GLIBCXX_HAVE_STRERROR_R
50 // Handle the result of POSIX strerror_r.
51 inline std::size_t
52 use_strerror_result(int res, char* buf, std::size_t bufsz,
53 std::size_t& nextbufsz)
55 if (res == 0) // Success.
56 return std::strlen(buf);
58 if (res == ERANGE) // Buffer too small to hold result string.
60 nextbufsz = 2 * bufsz;
61 return 0;
63 // else res == EINVAL, unknown error.
64 if (*buf == '\0') // No result string written to buffer.
66 const char msg[] = "Unknown error";
67 std::memcpy(buf, msg, sizeof(msg) - 1);
68 return sizeof(msg) - 1;
70 else // An "unknown error" string was already written to the buffer.
71 return std::strlen(buf);
74 // Handle the result of GNU strerror_r.
75 inline std::size_t
76 use_strerror_result(char* res, char* buf, std::size_t bufsz,
77 std::size_t& nextbufsz)
79 if (res == buf) // Result string written to the buffer.
80 return std::strlen(res);
82 // Static result string returned, must be copied to the buffer.
83 std::size_t len = std::strlen(res);
84 if (len <= bufsz)
86 std::strcpy(buf, res);
87 return len;
90 // Reallocate and try again:
91 nextbufsz = len;
92 return 0;
95 string strerror_string(int err)
97 // Estimate maximum length of strerror strings (including "Unknown error").
98 // Any excess capacity here can be used by std::system_error constructors
99 // when concatenating strings.
100 std::size_t len = 60;
101 string s;
103 s.__resize_and_overwrite(len, [err, &len](char* p, std::size_t n) {
104 *p = '\0';
105 return use_strerror_result(strerror_r(err, p, n), p, n, len);
107 while (s.empty());
108 return s;
110 #else
111 string strerror_string(int err)
113 return strerror(err); // XXX Not thread-safe.
115 #endif
117 template<typename T>
118 struct constant_init
120 union {
121 T obj;
123 constexpr constant_init() : obj() { }
125 ~constant_init() { /* do nothing, union member is not destroyed */ }
128 struct generic_error_category final : public std::error_category
130 const char*
131 name() const noexcept final
132 { return "generic"; }
134 _GLIBCXX_DEFAULT_ABI_TAG
135 string
136 message(int i) const final
137 { return strerror_string(i); }
139 // Override this to avoid a virtual call to default_error_condition(i).
140 bool
141 equivalent(int i, const std::error_condition& cond) const noexcept final
142 { return i == cond.value() && *this == cond.category(); }
145 __constinit constant_init<generic_error_category> generic_category_instance{};
147 struct system_error_category final : public std::error_category
149 const char*
150 name() const noexcept final
151 { return "system"; }
153 _GLIBCXX_DEFAULT_ABI_TAG
154 string
155 message(int i) const final
157 #if defined(_WIN32) && !defined(__CYGWIN__)
158 char* buf = nullptr;
159 auto len
160 = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
161 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
162 nullptr,
164 LANG_USER_DEFAULT,
165 reinterpret_cast<LPTSTR>(&buf),
167 nullptr);
168 if (len > 0)
170 struct deleter {
171 void operator()(void* p) const { ::LocalFree(p); }
173 std::unique_ptr<char[], deleter> guard(buf);
174 if (len > 3 && !__builtin_memcmp(buf + len - 3, ".\r\n", 3)) [[likely]]
175 len -= 3;
176 return string(buf, len);
178 return string("Unknown error code");
179 #else
180 return strerror_string(i);
181 #endif
184 std::error_condition
185 default_error_condition(int ev) const noexcept final
187 // Use generic category for all known POSIX errno values (including zero)
188 // and system category otherwise.
189 switch (ev)
191 #if defined(_WIN32) && !defined(__CYGWIN__)
192 case 0:
193 return {0, generic_category_instance.obj};
194 // Convert Windows error code into a corresponding POSIX errno value.
195 #define X(w, e) case ERROR_##w: return {e, generic_category_instance.obj};
196 // This list is based on Cygwin's winsup/cygwin/errno.cc
197 X (ACCESS_DENIED, EACCES);
198 X (ACTIVE_CONNECTIONS, EAGAIN);
199 X (ALREADY_EXISTS, EEXIST);
200 X (BAD_DEVICE, ENODEV);
201 X (BAD_EXE_FORMAT, ENOEXEC);
202 X (BAD_NETPATH, ENOENT);
203 X (BAD_NET_NAME, ENOENT);
204 X (BAD_NET_RESP, ENOSYS);
205 X (BAD_PATHNAME, ENOENT);
206 X (BAD_PIPE, EINVAL);
207 X (BAD_UNIT, ENODEV);
208 X (BAD_USERNAME, EINVAL);
209 X (BEGINNING_OF_MEDIA, EIO);
210 X (BROKEN_PIPE, EPIPE);
211 X (BUSY, EBUSY);
212 X (BUS_RESET, EIO);
213 X (CALL_NOT_IMPLEMENTED, ENOSYS);
214 X (CANCELLED, EINTR);
215 X (CANNOT_MAKE, EPERM);
216 X (CHILD_NOT_COMPLETE, EBUSY);
217 X (COMMITMENT_LIMIT, EAGAIN);
218 X (CONNECTION_REFUSED, ECONNREFUSED);
219 X (CRC, EIO);
220 X (DEVICE_DOOR_OPEN, EIO);
221 X (DEVICE_IN_USE, EAGAIN);
222 X (DEVICE_REQUIRES_CLEANING, EIO);
223 X (DEV_NOT_EXIST, ENOENT);
224 X (DIRECTORY, ENOTDIR);
225 X (DIR_NOT_EMPTY, ENOTEMPTY);
226 X (DISK_CORRUPT, EIO);
227 #ifdef ENOSPC
228 X (DISK_FULL, ENOSPC);
229 #endif
230 X (DS_GENERIC_ERROR, EIO);
231 #ifdef ENOSPC
232 X (END_OF_MEDIA, ENOSPC);
233 #endif
234 X (EOM_OVERFLOW, EIO);
235 X (EXE_MACHINE_TYPE_MISMATCH, ENOEXEC);
236 X (EXE_MARKED_INVALID, ENOEXEC);
237 X (FILEMARK_DETECTED, EIO);
238 X (FILENAME_EXCED_RANGE, ENAMETOOLONG);
239 X (FILE_CORRUPT, EEXIST);
240 X (FILE_EXISTS, EEXIST);
241 X (FILE_INVALID, ENXIO);
242 X (FILE_NOT_FOUND, ENOENT);
243 #ifdef ENOSPC
244 X (HANDLE_DISK_FULL, ENOSPC);
245 #endif
246 X (INVALID_ADDRESS, EINVAL);
247 X (INVALID_AT_INTERRUPT_TIME, EINTR);
248 X (INVALID_BLOCK_LENGTH, EIO);
249 X (INVALID_DATA, EINVAL);
250 X (INVALID_DRIVE, ENODEV);
251 X (INVALID_EA_NAME, EINVAL);
252 X (INVALID_EXE_SIGNATURE, ENOEXEC);
253 X (INVALID_HANDLE, EBADF);
254 X (INVALID_NAME, ENOENT);
255 X (INVALID_PARAMETER, EINVAL);
256 X (INVALID_SIGNAL_NUMBER, EINVAL);
257 X (IOPL_NOT_ENABLED, ENOEXEC);
258 X (IO_DEVICE, EIO);
259 X (IO_INCOMPLETE, EAGAIN);
260 X (IO_PENDING, EAGAIN);
261 X (LOCK_VIOLATION, EBUSY);
262 X (MAX_THRDS_REACHED, EAGAIN);
263 X (META_EXPANSION_TOO_LONG, EINVAL);
264 X (MOD_NOT_FOUND, ENOENT);
265 X (MORE_DATA, EMSGSIZE);
266 X (NEGATIVE_SEEK, EINVAL);
267 X (NETNAME_DELETED, ENOENT);
268 X (NOACCESS, EFAULT);
269 X (NONE_MAPPED, EINVAL);
270 X (NONPAGED_SYSTEM_RESOURCES, EAGAIN);
271 X (NOT_ENOUGH_MEMORY, ENOMEM);
272 X (NOT_ENOUGH_QUOTA, EIO);
273 #ifdef EPERM
274 X (NOT_OWNER, EPERM);
275 #else
276 X (NOT_OWNER, EACCES);
277 #endif
278 X (NOT_SAME_DEVICE, EXDEV);
279 X (NOT_SUPPORTED, ENOSYS);
280 X (NO_DATA, EPIPE);
281 X (NO_DATA_DETECTED, EIO);
282 X (NO_MORE_SEARCH_HANDLES, ENFILE);
283 X (NO_PROC_SLOTS, EAGAIN);
284 X (NO_SIGNAL_SENT, EIO);
285 X (NO_SYSTEM_RESOURCES, EFBIG);
286 X (NO_TOKEN, EINVAL);
287 X (OPEN_FAILED, EIO);
288 X (OPEN_FILES, EAGAIN);
289 X (OUTOFMEMORY, ENOMEM);
290 X (PAGED_SYSTEM_RESOURCES, EAGAIN);
291 X (PAGEFILE_QUOTA, EAGAIN);
292 X (PATH_NOT_FOUND, ENOENT);
293 X (PIPE_BUSY, EBUSY);
294 X (PIPE_CONNECTED, EBUSY);
295 X (POSSIBLE_DEADLOCK, EDEADLK);
296 X (PRIVILEGE_NOT_HELD, EPERM);
297 X (PROCESS_ABORTED, EFAULT);
298 X (PROC_NOT_FOUND, ESRCH);
299 X (SECTOR_NOT_FOUND, EINVAL);
300 X (SEEK, EINVAL);
301 X (SERVICE_REQUEST_TIMEOUT, EBUSY);
302 X (SETMARK_DETECTED, EIO);
303 X (SHARING_BUFFER_EXCEEDED, ENOLCK);
304 X (SHARING_VIOLATION, EBUSY);
305 X (SIGNAL_PENDING, EBUSY);
306 X (SIGNAL_REFUSED, EIO);
307 X (THREAD_1_INACTIVE, EINVAL);
308 X (TIMEOUT, EBUSY);
309 X (TOO_MANY_LINKS, EMLINK);
310 X (TOO_MANY_OPEN_FILES, EMFILE);
311 X (UNEXP_NET_ERR, EIO);
312 X (WORKING_SET_QUOTA, EAGAIN);
313 X (WRITE_PROTECT, EROFS);
314 #undef X
316 #elif defined __AVR__
317 // avr-libc only defines a few distinct error numbers. Most <errno.h>
318 // constants are not usable in #if directives and have the same value.
319 case EDOM:
320 case ERANGE:
321 case ENOSYS:
322 case EINTR:
323 case 0:
324 return std::error_condition(ev, generic_category_instance.obj);
325 #else
326 // List of errno macros from [cerrno.syn].
327 // C11 only defines EDOM, EILSEQ and ERANGE, the rest are from POSIX.
328 // They expand to integer constant expressions with type int,
329 // and distinct positive values, suitable for use in #if directives.
330 // POSIX adds more macros (but they're not defined on all targets,
331 // see config/os/.../error_constants.h), and POSIX allows
332 // EAGAIN == EWOULDBLOCK and ENOTSUP == EOPNOTSUPP.
334 #ifdef E2BIG
335 case E2BIG:
336 #endif
337 #ifdef EACCES
338 case EACCES:
339 #endif
340 #ifdef EADDRINUSE
341 case EADDRINUSE:
342 #endif
343 #ifdef EADDRNOTAVAIL
344 case EADDRNOTAVAIL:
345 #endif
346 #ifdef EAFNOSUPPORT
347 case EAFNOSUPPORT:
348 #endif
349 #ifdef EAGAIN
350 case EAGAIN:
351 #endif
352 #ifdef EALREADY
353 case EALREADY:
354 #endif
355 #ifdef EBADF
356 case EBADF:
357 #endif
358 #ifdef EBADMSG
359 case EBADMSG:
360 #endif
361 #ifdef EBUSY
362 case EBUSY:
363 #endif
364 #ifdef ECANCELED
365 case ECANCELED:
366 #endif
367 #ifdef ECHILD
368 case ECHILD:
369 #endif
370 #ifdef ECONNABORTED
371 case ECONNABORTED:
372 #endif
373 #ifdef ECONNREFUSED
374 case ECONNREFUSED:
375 #endif
376 #ifdef ECONNRESET
377 case ECONNRESET:
378 #endif
379 #ifdef EDEADLK
380 case EDEADLK:
381 #endif
382 #ifdef EDESTADDRREQ
383 case EDESTADDRREQ:
384 #endif
385 case EDOM:
386 #ifdef EEXIST
387 case EEXIST:
388 #endif
389 #ifdef EFAULT
390 case EFAULT:
391 #endif
392 #ifdef EFBIG
393 case EFBIG:
394 #endif
395 #ifdef EHOSTUNREACH
396 case EHOSTUNREACH:
397 #endif
398 #ifdef EIDRM
399 case EIDRM:
400 #endif
401 case EILSEQ:
402 #ifdef EINPROGRESS
403 case EINPROGRESS:
404 #endif
405 #ifdef EINTR
406 case EINTR:
407 #endif
408 #ifdef EINVAL
409 case EINVAL:
410 #endif
411 #ifdef EIO
412 case EIO:
413 #endif
414 #ifdef EISCONN
415 case EISCONN:
416 #endif
417 #ifdef EISDIR
418 case EISDIR:
419 #endif
420 #ifdef ELOOP
421 case ELOOP:
422 #endif
423 #ifdef EMFILE
424 case EMFILE:
425 #endif
426 #ifdef EMLINK
427 case EMLINK:
428 #endif
429 #ifdef EMSGSIZE
430 case EMSGSIZE:
431 #endif
432 #ifdef ENAMETOOLONG
433 case ENAMETOOLONG:
434 #endif
435 #ifdef ENETDOWN
436 case ENETDOWN:
437 #endif
438 #ifdef ENETRESET
439 case ENETRESET:
440 #endif
441 #ifdef ENETUNREACH
442 case ENETUNREACH:
443 #endif
444 #ifdef ENFILE
445 case ENFILE:
446 #endif
447 #ifdef ENOBUFS
448 case ENOBUFS:
449 #endif
450 #ifdef ENODATA
451 case ENODATA:
452 #endif
453 #ifdef ENODEV
454 case ENODEV:
455 #endif
456 #ifdef ENOENT
457 case ENOENT:
458 #endif
459 #ifdef ENOEXEC
460 case ENOEXEC:
461 #endif
462 #ifdef ENOLCK
463 case ENOLCK:
464 #endif
465 #ifdef ENOLINK
466 case ENOLINK:
467 #endif
468 #ifdef ENOMEM
469 case ENOMEM:
470 #endif
471 #ifdef ENOMSG
472 case ENOMSG:
473 #endif
474 #ifdef ENOPROTOOPT
475 case ENOPROTOOPT:
476 #endif
477 #ifdef ENOSPC
478 case ENOSPC:
479 #endif
480 #ifdef ENOSR
481 case ENOSR:
482 #endif
483 #ifdef ENOSTR
484 case ENOSTR:
485 #endif
486 #ifdef ENOSYS
487 case ENOSYS:
488 #endif
489 #ifdef ENOTCONN
490 case ENOTCONN:
491 #endif
492 #ifdef ENOTDIR
493 case ENOTDIR:
494 #endif
495 #if defined ENOTEMPTY && (!defined EEXIST || ENOTEMPTY != EEXIST)
496 // AIX sometimes uses the same value for EEXIST and ENOTEMPTY
497 case ENOTEMPTY:
498 #endif
499 #ifdef ENOTRECOVERABLE
500 case ENOTRECOVERABLE:
501 #endif
502 #ifdef ENOTSOCK
503 case ENOTSOCK:
504 #endif
505 #if defined ENOTSUP && (!defined ENOSYS || ENOTSUP != ENOSYS)
506 // zTPF uses the same value for ENOSYS and ENOTSUP
507 case ENOTSUP:
508 #endif
509 #ifdef ENOTTY
510 case ENOTTY:
511 #endif
512 #ifdef ENXIO
513 case ENXIO:
514 #endif
515 #if defined EOPNOTSUPP && (!defined ENOTSUP || EOPNOTSUPP != ENOTSUP)
516 case EOPNOTSUPP:
517 #endif
518 #ifdef EOVERFLOW
519 case EOVERFLOW:
520 #endif
521 #ifdef EOWNERDEAD
522 case EOWNERDEAD:
523 #endif
524 #ifdef EPERM
525 case EPERM:
526 #endif
527 #ifdef EPIPE
528 case EPIPE:
529 #endif
530 #ifdef EPROTO
531 case EPROTO:
532 #endif
533 #ifdef EPROTONOSUPPORT
534 case EPROTONOSUPPORT:
535 #endif
536 #ifdef EPROTOTYPE
537 case EPROTOTYPE:
538 #endif
539 case ERANGE:
540 #ifdef EROFS
541 case EROFS:
542 #endif
543 #ifdef ESPIPE
544 case ESPIPE:
545 #endif
546 #ifdef ESRCH
547 case ESRCH:
548 #endif
549 #ifdef ETIME
550 case ETIME:
551 #endif
552 #ifdef ETIMEDOUT
553 case ETIMEDOUT:
554 #endif
555 #ifdef ETXTBSY
556 case ETXTBSY:
557 #endif
558 #if defined EWOULDBLOCK && (!defined EAGAIN || EWOULDBLOCK != EAGAIN)
559 case EWOULDBLOCK:
560 #endif
561 #ifdef EXDEV
562 case EXDEV:
563 #endif
564 case 0:
565 return std::error_condition(ev, generic_category_instance.obj);
567 /* Additional system-dependent mappings from non-standard error codes
568 * to one of the POSIX values above would go here, e.g.
569 case EBLAH:
570 return std::error_condition(EINVAL, std::generic_category());
573 #endif
574 default:
575 return std::error_condition(ev, *this);
579 // Override this to avoid a virtual call to default_error_condition(i).
580 bool
581 equivalent(int i, const std::error_condition& cond) const noexcept final
582 { return system_error_category::default_error_condition(i) == cond; }
585 __constinit constant_init<system_error_category> system_category_instance{};
588 namespace std _GLIBCXX_VISIBILITY(default)
590 _GLIBCXX_BEGIN_NAMESPACE_VERSION
592 void
593 __throw_system_error(int __i __attribute__((unused)))
595 _GLIBCXX_THROW_OR_ABORT(system_error(__i, generic_category_instance.obj));
598 error_category::~error_category() = default;
600 _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
602 const error_category&
603 system_category() noexcept { return system_category_instance.obj; }
605 const error_category&
606 generic_category() noexcept { return generic_category_instance.obj; }
608 _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
610 system_error::~system_error() = default;
612 error_condition
613 error_category::default_error_condition(int __i) const noexcept
614 { return error_condition(__i, *this); }
616 bool
617 error_category::equivalent(int __i,
618 const error_condition& __cond) const noexcept
619 { return default_error_condition(__i) == __cond; }
621 bool
622 error_category::equivalent(const error_code& __code, int __i) const noexcept
623 { return *this == __code.category() && __code.value() == __i; }
625 error_condition
626 error_code::default_error_condition() const noexcept
627 { return category().default_error_condition(value()); }
629 #if _GLIBCXX_USE_CXX11_ABI
630 // Return error_category::message() as a COW string
631 __cow_string
632 error_category::_M_message(int i) const
634 string msg = this->message(i);
635 return {msg.c_str(), msg.length()};
637 #endif
639 _GLIBCXX_END_NAMESPACE_VERSION
640 } // namespace