1/* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */ 2/* Public Domain <marc@snafu.org> */ 3 4// G++ automatically defines _GNU_SOURCE, which then means that <string.h> 5// gives us the GNU variant. 6#undef _GNU_SOURCE 7 8#include <string.h> 9 10#include <errno.h> 11#include <limits.h> 12#include <signal.h> 13#include <stdio.h> 14 15#include "private/ErrnoRestorer.h" 16#include "private/libc_logging.h" 17 18struct Pair { 19 int code; 20 const char* msg; 21}; 22 23static const char* __code_string_lookup(const Pair* strings, int code) { 24 for (size_t i = 0; strings[i].msg != NULL; ++i) { 25 if (strings[i].code == code) { 26 return strings[i].msg; 27 } 28 } 29 return NULL; 30} 31 32static const Pair _sys_error_strings[] = { 33#define __BIONIC_ERRDEF(x,y,z) { x, z }, 34#include "private/bionic_errdefs.h" 35 { 0, NULL } 36}; 37 38extern "C" __LIBC_HIDDEN__ const char* __strerror_lookup(int error_number) { 39 return __code_string_lookup(_sys_error_strings, error_number); 40} 41 42static const Pair _sys_signal_strings[] = { 43#define __BIONIC_SIGDEF(signal_number, signal_description) { signal_number, signal_description }, 44#include "private/bionic_sigdefs.h" 45 { 0, NULL } 46}; 47 48extern "C" __LIBC_HIDDEN__ const char* __strsignal_lookup(int signal_number) { 49 return __code_string_lookup(_sys_signal_strings, signal_number); 50} 51 52int strerror_r(int error_number, char* buf, size_t buf_len) { 53 ErrnoRestorer errno_restorer; 54 size_t length; 55 56 const char* error_name = __strerror_lookup(error_number); 57 if (error_name != NULL) { 58 length = strlcpy(buf, error_name, buf_len); 59 } else { 60 length = __libc_format_buffer(buf, buf_len, "Unknown error %d", error_number); 61 } 62 if (length >= buf_len) { 63 errno_restorer.override(ERANGE); 64 return -1; 65 } 66 67 return 0; 68} 69 70extern "C" char* __gnu_strerror_r(int error_number, char* buf, size_t buf_len) { 71 ErrnoRestorer errno_restorer; // The glibc strerror_r doesn't set errno if it truncates... 72 strerror_r(error_number, buf, buf_len); 73 return buf; // ...and just returns whatever fit. 74} 75 76extern "C" __LIBC_HIDDEN__ const char* __strsignal(int signal_number, char* buf, size_t buf_len) { 77 const char* signal_name = __strsignal_lookup(signal_number); 78 if (signal_name != NULL) { 79 return signal_name; 80 } 81 82 const char* prefix = "Unknown"; 83 if (signal_number >= SIGRTMIN && signal_number <= SIGRTMAX) { 84 prefix = "Real-time"; 85 signal_number -= SIGRTMIN; 86 } 87 size_t length = snprintf(buf, buf_len, "%s signal %d", prefix, signal_number); 88 if (length >= buf_len) { 89 return NULL; 90 } 91 return buf; 92} 93