1b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea/* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */ 2b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea/* Public Domain <marc@snafu.org> */ 3b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 4416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes// G++ automatically defines _GNU_SOURCE, which then means that <string.h> 5416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes// gives us the GNU variant. 6416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes#undef _GNU_SOURCE 7416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes 8416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes#include <string.h> 9416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes 10b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#include <errno.h> 11b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#include <limits.h> 12b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#include <signal.h> 13b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#include <stdio.h> 14b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 153e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes#include "private/ErrnoRestorer.h" 1691570ce987ef93f9ba2fa663a5fee1bd2525a2baElliott Hughes#include "private/libc_logging.h" 173e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 18b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdeastruct Pair { 19b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea int code; 20b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea const char* msg; 21b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea}; 22b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 23b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdeastatic const char* __code_string_lookup(const Pair* strings, int code) { 24b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea for (size_t i = 0; strings[i].msg != NULL; ++i) { 25b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea if (strings[i].code == code) { 26b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea return strings[i].msg; 27b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } 28b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } 29b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea return NULL; 30b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea} 31b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 32b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdeastatic const Pair _sys_error_strings[] = { 33b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#define __BIONIC_ERRDEF(x,y,z) { x, z }, 3426bc9c64d5b0cad921e3070a4f94fa04e1077d90Josh Gao#include "private/bionic_errdefs.h" 35b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea { 0, NULL } 36b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea}; 37b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 3895a7a64ac8b242f278f515b06bdb6057ecca4396Elliott Hughesextern "C" __LIBC_HIDDEN__ const char* __strerror_lookup(int error_number) { 394198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes return __code_string_lookup(_sys_error_strings, error_number); 404198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes} 414198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes 424198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughesstatic const Pair _sys_signal_strings[] = { 43aa0ebdafc71e1ceac78e0929b94f3bb117d0c8e9Elliott Hughes#define __BIONIC_SIGDEF(signal_number, signal_description) { signal_number, signal_description }, 4426bc9c64d5b0cad921e3070a4f94fa04e1077d90Josh Gao#include "private/bionic_sigdefs.h" 454198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes { 0, NULL } 464198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes}; 474198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes 4895a7a64ac8b242f278f515b06bdb6057ecca4396Elliott Hughesextern "C" __LIBC_HIDDEN__ const char* __strsignal_lookup(int signal_number) { 494198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes return __code_string_lookup(_sys_signal_strings, signal_number); 504198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes} 514198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes 52b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdeaint strerror_r(int error_number, char* buf, size_t buf_len) { 533e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes ErrnoRestorer errno_restorer; 54b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea size_t length; 55b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 564198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes const char* error_name = __strerror_lookup(error_number); 57b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea if (error_name != NULL) { 5891570ce987ef93f9ba2fa663a5fee1bd2525a2baElliott Hughes length = strlcpy(buf, error_name, buf_len); 59b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } else { 6091570ce987ef93f9ba2fa663a5fee1bd2525a2baElliott Hughes length = __libc_format_buffer(buf, buf_len, "Unknown error %d", error_number); 61b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } 62b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea if (length >= buf_len) { 633e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes errno_restorer.override(ERANGE); 64b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea return -1; 65b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } 66b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 67b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea return 0; 68b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea} 69b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 70416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughesextern "C" char* __gnu_strerror_r(int error_number, char* buf, size_t buf_len) { 71416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes ErrnoRestorer errno_restorer; // The glibc strerror_r doesn't set errno if it truncates... 72416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes strerror_r(error_number, buf, buf_len); 73416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes return buf; // ...and just returns whatever fit. 74416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes} 75416d7ddaff0946d480b6aa945a741b3eeaca5569Elliott Hughes 7695a7a64ac8b242f278f515b06bdb6057ecca4396Elliott Hughesextern "C" __LIBC_HIDDEN__ const char* __strsignal(int signal_number, char* buf, size_t buf_len) { 774198fa4c23fc8a1895808a597bb153530f6ea515Elliott Hughes const char* signal_name = __strsignal_lookup(signal_number); 78b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea if (signal_name != NULL) { 79b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea return signal_name; 80b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } 81b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea 82b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea const char* prefix = "Unknown"; 83b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea if (signal_number >= SIGRTMIN && signal_number <= SIGRTMAX) { 84b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea prefix = "Real-time"; 85b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea signal_number -= SIGRTMIN; 86b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } 87b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea size_t length = snprintf(buf, buf_len, "%s signal %d", prefix, signal_number); 88b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea if (length >= buf_len) { 89b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea return NULL; 90b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea } 91b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea return buf; 92b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea} 93