[systemd-devel] [RFC 22/25] support POSIX strerror_r returning int

Emil Renner Berthing systemd at esmil.dk
Thu Sep 18 06:24:58 PDT 2014


---
 configure.ac                      |  2 ++
 src/journal/journal-send.c        | 36 +++++++++++++++++++++++++++---------
 src/libsystemd/sd-bus/bus-error.c | 14 +++++++++++++-
 3 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/configure.ac b/configure.ac
index 9cd4c05..3f17833 100644
--- a/configure.ac
+++ b/configure.ac
@@ -336,6 +336,8 @@ AC_CHECK_DECLS([IFLA_MACVLAN_FLAGS,
 #include <linux/if_bridge.h>
 ]])
 
+AC_FUNC_STRERROR_R
+
 # This makes sure pkg.m4 is available.
 m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
 
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index 9ca4a0b..62b40b2 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -341,6 +341,29 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
         return 0;
 }
 
+#ifdef STRERROR_R_CHAR_P
+static int posix_strerror_r(int errnum, char *buf, size_t buflen) {
+        char *res;
+
+        errno = 0;
+        res = strerror_r(errnum, buf, buflen);
+        if (errno)
+                return errno;
+
+        if (res != buf) {
+                size_t len = strlen(res)+1;
+
+                if (len > buflen)
+                        return ERANGE;
+
+                memmove(buf, res, len);
+        }
+        return 0;
+}
+#else
+#define posix_strerror_r strerror_r
+#endif
+
 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
         PROTECT_ERRNO;
         size_t n, k;
@@ -350,16 +373,11 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove
 
         for (;;) {
                 char buffer[n];
-                char* j;
+                int ret = posix_strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
 
-                errno = 0;
-                j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
-                if (errno == 0) {
+                if (ret == 0) {
                         char error[6 + 10 + 1]; /* for a 32bit value */
 
-                        if (j != buffer + 8 + k)
-                                memmove(buffer + 8 + k, j, strlen(j)+1);
-
                         memcpy(buffer, "MESSAGE=", 8);
 
                         if (k > 0) {
@@ -377,8 +395,8 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove
                         return sd_journal_sendv(iov, skip + 3);
                 }
 
-                if (errno != ERANGE)
-                        return -errno;
+                if (ret != ERANGE)
+                        return -ret;
 
                 n *= 2;
         }
diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c
index c2e41fb..14bbaca 100644
--- a/src/libsystemd/sd-bus/bus-error.c
+++ b/src/libsystemd/sd-bus/bus-error.c
@@ -291,6 +291,18 @@ _public_ int sd_bus_error_get_errno(const sd_bus_error* e) {
         return bus_error_name_to_errno(e->name);
 }
 
+#ifdef STRERROR_R_CHAR_P
+#define gnu_strerror_r strerror_r
+#else
+static char *gnu_strerror_r(int errnum, char *buf, size_t buflen) {
+        int ret = strerror_r(errnum, buf, buflen);
+
+        if (ret)
+                errno = ret;
+        return buf;
+}
+#endif
+
 static void bus_error_strerror(sd_bus_error *e, int error) {
         size_t k = 64;
         char *m;
@@ -305,7 +317,7 @@ static void bus_error_strerror(sd_bus_error *e, int error) {
                         return;
 
                 errno = 0;
-                x = strerror_r(error, m, k);
+                x = gnu_strerror_r(error, m, k);
                 if (errno == ERANGE || strlen(x) >= k - 1) {
                         free(m);
                         k *= 2;
-- 
2.1.0



More information about the systemd-devel mailing list