Signed-off-by: Ben Pfaff <b...@nicira.com> --- 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 dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev