[PATCH 1/3] lib: add utility function nl_strerror_l()

git at andred.net git at andred.net
Thu Aug 25 05:14:59 PDT 2016


From: André Draszik <adraszik at tycoint.com>

libnl currently uses strerror_r() throughout, but this is
problematic because there is a non-standard GNU version
implemented in glibc, and the standard POSIX version, which
differ in signature. When using glibc, one can choose
between the two versions using feature test macros
_GNU_SOURCE and _POSIX_C_SOURCE.

Given libnl is built using the former, we always get the
glibc special version, and all code so far has been written
for that non-standard version.

Other C libraries like musl on the other hand only try
to be posix compliant, and only ever provide the posix
version of strerror_r(), which has a different signature.

The alternative is to use strerror_l() rather than
strerror_r() http://austingroupbugs.net/view.php?id=655
- this will avoid the non-confirming versions issue
- strerror_l() is now recommended by POSIX to replace
  strerror_r() usage

So rather than changing all uses of strerror_r() to be in
line with posix, we are going to switch to the recommended
interface strerror_l().

Since strerror_l() is slightly more difficuly to use, we
add a little (private) wrapper that we can use from all
current callsites of strerror_r().

Signed-off-by: André Draszik <adraszik at tycoint.com>
Reviewed-by: Stephane Ayotte <sayotte at tycoint.com>
---
 include/Makefile.am             |  1 +
 include/netlink-private/utils.h | 17 +++++++++++++++++
 lib/utils.c                     | 24 ++++++++++++++++++++++++
 libnl-3.sym                     |  5 +++++
 4 files changed, 47 insertions(+)
 create mode 100644 include/netlink-private/utils.h

diff --git a/include/Makefile.am b/include/Makefile.am
index 804e984..f8b977a 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -166,6 +166,7 @@ noinst_HEADERS = \
 	netlink-private/socket.h \
 	netlink-private/tc.h \
 	netlink-private/types.h \
+	netlink-private/utils.h \
 	netlink-private/cache-api.h \
 	netlink-private/object-api.h \
 	netlink-private/route/link/api.h \
diff --git a/include/netlink-private/utils.h b/include/netlink-private/utils.h
new file mode 100644
index 0000000..77aadb3
--- /dev/null
+++ b/include/netlink-private/utils.h
@@ -0,0 +1,17 @@
+/*
+ * netlink-private/utils.h	Local Utility Functions
+ *
+ *	This library is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU Lesser General Public
+ *	License as published by the Free Software Foundation version 2.1
+ *	of the License.
+ *
+ * Copyright (c) 2003-2012 Thomas Graf <tgraf at suug.ch>
+ */
+
+#ifndef NETLINK_UTILS_PRIV_H_
+#define NETLINK_UTILS_PRIV_H_
+
+extern const char *	nl_strerror_l(int err);
+
+#endif
diff --git a/lib/utils.c b/lib/utils.c
index 61c3d95..c1c1b72 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -25,10 +25,12 @@
  */
 
 #include <netlink-private/netlink.h>
+#include <netlink-private/utils.h>
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <linux/socket.h>
 #include <stdlib.h> /* exit() */
+#include <locale.h>
 
 /**
  * Global variable indicating the desired level of debugging output.
@@ -118,6 +120,28 @@ int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *))
 
 	return 0;
 }
+
+const char *nl_strerror_l(int err)
+{
+	int errno_save = errno;
+	locale_t loc = newlocale(LC_MESSAGES_MASK, "", (locale_t)0);
+	const char *buf;
+
+	if (loc == (locale_t)0) {
+		if (errno == ENOENT)
+			loc = newlocale(LC_MESSAGES_MASK,
+					"POSIX", (locale_t)0);
+	}
+	if (loc != (locale_t)0) {
+		buf = strerror_l(err, loc);
+		freelocale(loc);
+	} else {
+		buf = "newlocale() failed";
+	}
+
+	errno = errno_save;
+	return buf;
+}
 /** @endcond */
 
 /**
diff --git a/libnl-3.sym b/libnl-3.sym
index 4e09bdd..9119e66 100644
--- a/libnl-3.sym
+++ b/libnl-3.sym
@@ -351,3 +351,8 @@ libnl_3_2_28 {
 global:
 	nl_object_diff64;
 } libnl_3_2_27;
+
+libnl_3_2_29 {
+global:
+	nl_strerror_l;
+} libnl_3_2_28;
-- 
2.9.3




More information about the libnl mailing list