summaryrefslogtreecommitdiff
path: root/gnulib/lib/strerror.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnulib/lib/strerror.c')
-rw-r--r--gnulib/lib/strerror.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/gnulib/lib/strerror.c b/gnulib/lib/strerror.c
index 9fe437d..80a2f2e 100644
--- a/gnulib/lib/strerror.c
+++ b/gnulib/lib/strerror.c
@@ -1,6 +1,6 @@
/* strerror.c --- POSIX compatible system error routine
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,33 +17,54 @@
#include <config.h>
+/* Specification. */
#include <string.h>
-#if REPLACE_STRERROR
-
-# include <stdio.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-# include "intprops.h"
+#include "intprops.h"
+#include "strerror-override.h"
+#include "verify.h"
-# undef strerror
-# if ! HAVE_DECL_STRERROR
-# define strerror(n) NULL
-# endif
+/* Use the system functions, not the gnulib overrides in this file. */
+#undef sprintf
char *
-rpl_strerror (int n)
+strerror (int n)
+#undef strerror
{
- char *result = strerror (n);
+ static char buf[STACKBUF_LEN];
+ size_t len;
+
+ /* Cast away const, due to the historical signature of strerror;
+ callers should not be modifying the string. */
+ const char *msg = strerror_override (n);
+ if (msg)
+ return (char *) msg;
- if (result == NULL || result[0] == '\0')
+ msg = strerror (n);
+
+ /* Our strerror_r implementation might use the system's strerror
+ buffer, so all other clients of strerror have to see the error
+ copied into a buffer that we manage. This is not thread-safe,
+ even if the system strerror is, but portable programs shouldn't
+ be using strerror if they care about thread-safety. */
+ if (!msg || !*msg)
{
- static char const fmt[] = "Unknown error (%d)";
- static char mesg[sizeof fmt + INT_STRLEN_BOUND (n)];
- sprintf (mesg, fmt, n);
- return mesg;
+ static char const fmt[] = "Unknown error %d";
+ verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n));
+ sprintf (buf, fmt, n);
+ errno = EINVAL;
+ return buf;
}
- return result;
-}
+ /* Fix STACKBUF_LEN if this ever aborts. */
+ len = strlen (msg);
+ if (sizeof buf <= len)
+ abort ();
-#endif
+ return memcpy (buf, msg, len + 1);
+}