lib: use the POSIX version of strerror_r()

Switch from the GNU version of strerror_r() to the POSIX version, so
that the code will work on systems that only have the POSIX version.

Signed-off-by: Eric Biggers <ebiggers@google.com>
diff --git a/lib/lib_private.h b/lib/lib_private.h
index 7768eea..6af3cfc 100644
--- a/lib/lib_private.h
+++ b/lib/lib_private.h
@@ -52,6 +52,10 @@
 			   u8 *digest);
 void libfsverity_free_hash_ctx(struct hash_ctx *ctx);
 
+/* strerror.c */
+
+int libfsverity_strerror(int errnum, char *buf, size_t buflen);
+
 /* utils.c */
 
 void *libfsverity_zalloc(size_t size);
diff --git a/lib/strerror.c b/lib/strerror.c
new file mode 100644
index 0000000..c5b0bc5
--- /dev/null
+++ b/lib/strerror.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+/*
+ * The libfsverity_strerror() utility function
+ *
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by an MIT-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/MIT.
+ */
+
+/*
+ * Make sure we get the POSIX version of strerror_r() instead of the GNU version
+ * of strerror_r(), so that the code works on systems that have the POSIX
+ * version but not the GNU version (e.g., musl libc).
+ */
+#undef _GNU_SOURCE
+#define _POSIX_C_SOURCE 200112
+
+#include "lib_private.h"
+
+#include <string.h>
+
+int libfsverity_strerror(int errnum, char *buf, size_t buflen)
+{
+#ifdef _WIN32
+	return strerror_s(buf, buflen, errnum);
+#else
+	return strerror_r(errnum, buf, buflen);
+#endif
+}
diff --git a/lib/utils.c b/lib/utils.c
index 036dd60..4a346ff 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -51,15 +51,6 @@
 	libfsverity_error_cb = cb;
 }
 
-#ifdef _WIN32
-static char *strerror_r(int errnum, char *buf, size_t buflen)
-{
-	strerror_s(buf, buflen, errnum);
-
-	return buf;
-}
-#endif
-
 void libfsverity_do_error_msg(const char *format, va_list va, int err)
 {
 	int saved_errno = errno;
@@ -75,8 +66,10 @@
 		char *msg2 = NULL;
 		char errbuf[64];
 
-		if (asprintf(&msg2, "%s: %s", msg,
-			     strerror_r(err, errbuf, sizeof(errbuf))) < 0)
+		if (libfsverity_strerror(err, errbuf, sizeof(errbuf)) != 0)
+			goto out2;
+
+		if (asprintf(&msg2, "%s: %s", msg, errbuf) < 0)
 			goto out2;
 		free(msg);
 		msg = msg2;