Add posix_strerror_r and ErrnoNumberAsString to libbase

Calling strerror_r is tricky, as glibc provides the GNU version
if _GNU_SOURCE is set, and musl libc only provides the posix version.
Handle the complexity once in libbase to export a posix_strerror_r
function, and move update_engine's ErrnoNumberAsString into libbase.

Bug: 190084016
Test: m USE_HOST_MUSL=true host-native
Test: atest --host libbase_test
Change-Id: Ied24f5bb8cf34fc7948d129c368ee17adb1460e1
diff --git a/Android.bp b/Android.bp
index 5648d06..ff6bcc5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -85,6 +85,7 @@
         "mapped_file.cpp",
         "parsebool.cpp",
         "parsenetaddress.cpp",
+        "posix_strerror_r.cpp",
         "process.cpp",
         "properties.cpp",
         "stringprintf.cpp",
diff --git a/include/android-base/strings.h b/include/android-base/strings.h
index 95d6077..e794540 100644
--- a/include/android-base/strings.h
+++ b/include/android-base/strings.h
@@ -104,5 +104,8 @@
 [[nodiscard]] std::string StringReplace(std::string_view s, std::string_view from,
                                         std::string_view to, bool all);
 
+// Converts an errno number to its error message string.
+std::string ErrnoNumberAsString(int errnum);
+
 }  // namespace base
 }  // namespace android
diff --git a/posix_strerror_r.cpp b/posix_strerror_r.cpp
new file mode 100644
index 0000000..6428a98
--- /dev/null
+++ b/posix_strerror_r.cpp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/* Undefine _GNU_SOURCE so that this compilation unit can access the
+ * posix version of strerror_r */
+#undef _GNU_SOURCE
+#include <string.h>
+
+namespace android {
+namespace base {
+
+extern "C" int posix_strerror_r(int errnum, char* buf, size_t buflen) {
+#ifdef _WIN32
+  return strerror_s(buf, buflen, errnum);
+#else
+  return strerror_r(errnum, buf, buflen);
+#endif
+}
+
+}  // namespace base
+}  // namespace android
diff --git a/strings.cpp b/strings.cpp
index 8f3c7d9..deb6e28 100644
--- a/strings.cpp
+++ b/strings.cpp
@@ -16,12 +16,18 @@
 
 #include "android-base/strings.h"
 
+#include "android-base/stringprintf.h"
+
 #include <stdlib.h>
 #include <string.h>
 
 #include <string>
 #include <vector>
 
+// Wraps the posix version of strerror_r to make it available in translation units
+// that define _GNU_SOURCE.
+extern "C" int posix_strerror_r(int errnum, char* buf, size_t buflen);
+
 namespace android {
 namespace base {
 
@@ -152,5 +158,15 @@
   return result;
 }
 
+std::string ErrnoNumberAsString(int errnum) {
+  char buf[100];
+  buf[0] = '\0';
+  int strerror_err = posix_strerror_r(errnum, buf, sizeof(buf));
+  if (strerror_err < 0) {
+    return StringPrintf("Failed to convert errno %d to string: %d", errnum, strerror_err);
+  }
+  return buf;
+}
+
 }  // namespace base
 }  // namespace android
diff --git a/strings_test.cpp b/strings_test.cpp
index 7a57489..fb111b8 100644
--- a/strings_test.cpp
+++ b/strings_test.cpp
@@ -400,3 +400,7 @@
   ASSERT_EQ("xxyzx", android::base::StringReplace("abcxyzabc", "abc", "x", true));
   ASSERT_EQ("<xx>", android::base::StringReplace("<abcabc>", "abc", "x", true));
 }
+
+TEST(strings, ErrnoNumberAsString) {
+  EXPECT_EQ("No such file or directory", android::base::ErrnoNumberAsString(ENOENT));
+}