diff --git a/test/util/posix_error.cc b/test/util/posix_error.cc index 7b4b3524d..ead9ede16 100644 --- a/test/util/posix_error.cc +++ b/test/util/posix_error.cc @@ -32,13 +32,23 @@ std::string PosixError::ToString() const { std::string ret; char strerrno_buf[1024] = {}; - char* msg = nullptr; - if ((msg = strerror_r(errno_, strerrno_buf, sizeof(strerrno_buf))) == - nullptr) { - ret = absl::StrCat("PosixError(errno=", errno_, " strerror_r FAILED)"); + + auto res = strerror_r(errno_, strerrno_buf, sizeof(strerrno_buf)); + +// The GNU version of strerror_r always returns a non-null char* pointing to a +// buffer containing the stringified errno; the XSI version returns a positive +// errno which indicates the result of writing the stringified errno into the +// supplied buffer. The gymnastics below are needed to support both. +#ifndef _GNU_SOURCE + if (res != 0) { + ret = absl::StrCat("PosixError(errno=", errno_, " strerror_r FAILED(", ret, + "))"); } else { - ret = absl::StrCat("PosixError(errno=", errno_, " ", msg, ")"); + ret = absl::StrCat("PosixError(errno=", errno_, " ", strerrno_buf, ")"); } +#else + ret = absl::StrCat("PosixError(errno=", errno_, " ", res, ")"); +#endif if (!msg_.empty()) { ret.append(" "); diff --git a/test/util/test_util.h b/test/util/test_util.h index 37e40de8e..6f2fa4875 100644 --- a/test/util/test_util.h +++ b/test/util/test_util.h @@ -270,16 +270,6 @@ PosixErrorOr Links(const std::string& path); namespace internal { -inline std::string ErrnoWithMessage(int const errnum) { - char buf[1024] = {}; - const char* str = strerror_r(errnum, buf, sizeof(buf)); - if (str == nullptr || str[0] == '\0') { - snprintf(buf, sizeof(buf), "Unknown error %d", errnum); - str = buf; - } - return absl::StrCat(errnum, " (", str, ")"); -} - template class ElementOfMatcher { public: @@ -348,7 +338,7 @@ class SyscallSuccessMatcher { T const& rv, ::testing::MatchResultListener* const listener) const override { if (rv == static_cast(-1) && errno != 0) { - *listener << "with errno " << ErrnoWithMessage(errno); + *listener << "with errno " << PosixError(errno); return false; } bool match = matcher_.MatchAndExplain(rv, listener); @@ -416,7 +406,7 @@ class SyscallFailureMatcher { return false; } int actual_errno = errno; - *listener << "with errno " << ErrnoWithMessage(actual_errno); + *listener << "with errno " << PosixError(actual_errno); bool match = errno_matcher_.MatchAndExplain(actual_errno, listener); if (match) { MaybeSave(); @@ -449,11 +439,11 @@ class SpecificErrnoMatcher : public ::testing::MatcherInterface { } void DescribeTo(::std::ostream* const os) const override { - *os << ErrnoWithMessage(expected_); + *os << PosixError(expected_); } void DescribeNegationTo(::std::ostream* const os) const override { - *os << "not " << ErrnoWithMessage(expected_); + *os << "not " << PosixError(expected_); } private: