summaryrefslogtreecommitdiffstats
path: root/libc/bionic/strerror_r.cpp
diff options
context:
space:
mode:
authorIrina Tirdea <irina.tirdea@intel.com>2012-09-08 09:17:54 +0300
committerElliott Hughes <enh@google.com>2012-09-13 15:18:21 -0700
commitb5f053b5a7deb084e7a052d527e0aa41339ae05c (patch)
treea75d6715f7c7c954d22440b8c21c59b01d87e83d /libc/bionic/strerror_r.cpp
parent4a9b7c694a8312160d3cd953a8227c23a1624868 (diff)
downloadbionic-b5f053b5a7deb084e7a052d527e0aa41339ae05c.zip
bionic-b5f053b5a7deb084e7a052d527e0aa41339ae05c.tar.gz
bionic-b5f053b5a7deb084e7a052d527e0aa41339ae05c.tar.bz2
Make strerror(3) and strsignal(3) thread-safe, and add psignal(3) and psiginfo(3).
Change-Id: I426109db25e907980d6cb3a7a695796e45783b78
Diffstat (limited to 'libc/bionic/strerror_r.cpp')
-rw-r--r--libc/bionic/strerror_r.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/libc/bionic/strerror_r.cpp b/libc/bionic/strerror_r.cpp
new file mode 100644
index 0000000..92235a5
--- /dev/null
+++ b/libc/bionic/strerror_r.cpp
@@ -0,0 +1,71 @@
+/* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
+/* Public Domain <marc@snafu.org> */
+
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+struct Pair {
+ int code;
+ const char* msg;
+};
+
+static const char* __code_string_lookup(const Pair* strings, int code) {
+ for (size_t i = 0; strings[i].msg != NULL; ++i) {
+ if (strings[i].code == code) {
+ return strings[i].msg;
+ }
+ }
+ return NULL;
+}
+
+static const Pair _sys_error_strings[] = {
+#define __BIONIC_ERRDEF(x,y,z) { x, z },
+#include <sys/_errdefs.h>
+ { 0, NULL }
+};
+
+int strerror_r(int error_number, char* buf, size_t buf_len) {
+ int saved_errno = errno;
+ size_t length;
+
+ const char* error_name = __code_string_lookup(_sys_error_strings, error_number);
+ if (error_name != NULL) {
+ length = snprintf(buf, buf_len, "%s", error_name);
+ } else {
+ length = snprintf(buf, buf_len, "Unknown error %u", error_number);
+ }
+ if (length >= buf_len) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ errno = saved_errno;
+ return 0;
+}
+
+static const Pair _sys_signal_strings[] = {
+#define __BIONIC_SIGDEF(x,y,z) { y, z },
+#include <sys/_sigdefs.h>
+ { 0, NULL }
+};
+
+extern "C" const char* __strsignal(int signal_number, char* buf, size_t buf_len) {
+ const char* signal_name = __code_string_lookup(_sys_signal_strings, signal_number);
+ if (signal_name != NULL) {
+ return signal_name;
+ }
+
+ const char* prefix = "Unknown";
+ if (signal_number >= SIGRTMIN && signal_number <= SIGRTMAX) {
+ prefix = "Real-time";
+ signal_number -= SIGRTMIN;
+ }
+ size_t length = snprintf(buf, buf_len, "%s signal %d", prefix, signal_number);
+ if (length >= buf_len) {
+ return NULL;
+ }
+ return buf;
+}