Signed-off-by: Ben Pfaff <[email protected]>
---
configure.ac | 1 +
lib/util.c | 48 +++++++++++++++++++++++++++++++++++++-----------
lib/util.h | 3 ++-
3 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/configure.ac b/configure.ac
index 6db4a00..734b2ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,7 @@ AC_SEARCH_LIBS([pow], [m])
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_SEARCH_LIBS([timer_create], [rt])
AC_SEARCH_LIBS([pthread_sigmask], [pthread])
+AC_FUNC_STRERROR_R
OVS_CHECK_ESX
OVS_CHECK_COVERAGE
diff --git a/lib/util.c b/lib/util.c
index 2a06461..6ee8b5c 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -18,6 +18,7 @@
#include "util.h"
#include <errno.h>
#include <limits.h>
+#include <pthread.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -45,6 +46,9 @@ const char *subprogram_name = "";
/* --version option output. */
static char *program_version;
+/* Buffer used by ovs_strerror(). */
+DEFINE_PER_THREAD_DATA(struct { char s[128]; }, strerror_buffer, { "" });
+
void
ovs_assert_failure(const char *where, const char *function,
const char *condition)
@@ -307,19 +311,41 @@ ovs_error_valist(int err_no, const char *format, va_list
args)
const char *
ovs_retval_to_string(int retval)
{
- static char unknown[48];
+ return (!retval ? ""
+ : retval == EOF ? "End of file"
+ : ovs_strerror(retval));
+}
- if (!retval) {
- return "";
- }
- if (retval > 0) {
- return strerror(retval);
- }
- if (retval == EOF) {
- return "End of file";
+const char *
+ovs_strerror(int error)
+{
+ enum { BUFSIZE = sizeof strerror_buffer_get()->s };
+ int save_errno;
+ char *buffer;
+ char *s;
+
+ save_errno = errno;
+ buffer = strerror_buffer_get()->s;
+
+#if STRERROR_R_CHAR_P
+ /* GNU style strerror_r() might return an immutable static string, or it
+ * might write and return 'buffer', but in either case we can pass the
+ * returned string directly to the caller. */
+ s = strerror_r(error, buffer, BUFSIZE);
+#else /* strerror_r() returns an int. */
+ s = buffer;
+ if (strerror_r(error, buffer, BUFSIZE)) {
+ /* strerror_r() is only allowed to fail on ERANGE (because the buffer
+ * is too short). We don't check the actual failure reason because
+ * POSIX requires strerror_r() to return the error but old glibc
+ * (before 2.13) returns -1 and sets errno. */
+ snprintf(buffer, ptb.bufsize, "Unknown error %d", error);
}
- snprintf(unknown, sizeof unknown, "***unknown return value: %d***",
retval);
- return unknown;
+#endif
+
+ errno = save_errno;
+
+ return s;
}
/* Sets global "program_name" and "program_version" variables. Should
diff --git a/lib/util.h b/lib/util.h
index f5589e3..d7fbe09 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -213,6 +213,7 @@ void ovs_error(int err_no, const char *format, ...)
PRINTF_FORMAT(2, 3);
void ovs_error_valist(int err_no, const char *format, va_list)
PRINTF_FORMAT(2, 0);
const char *ovs_retval_to_string(int);
+const char *ovs_strerror(int);
void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii);
bool str_to_int(const char *, int base, int *);
--
1.7.2.5
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev