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));
+}