gettimeofday: port recent C++ fix to Emacs
[gnulib.git] / lib / strerror.c
index f0e03df..80a2f2e 100644 (file)
@@ -1,6 +1,6 @@
 /* strerror.c --- POSIX compatible system error routine
 
-   Copyright (C) 2007-2011 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
 /* Specification.  */
 #include <string.h>
 
-#if REPLACE_STRERROR
-
-# include <errno.h>
-# include <stdio.h>
-# include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
-# include "intprops.h"
-# include "verify.h"
+#include "intprops.h"
+#include "strerror-override.h"
+#include "verify.h"
 
 /* Use the system functions, not the gnulib overrides in this file.  */
-# undef sprintf
+#undef sprintf
+
+char *
+strerror (int n)
+#undef strerror
+{
+  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;
+
+  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";
+      verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n));
+      sprintf (buf, fmt, n);
+      errno = EINVAL;
+      return buf;
+    }
 
-# include "strerror-impl.h"
+  /* Fix STACKBUF_LEN if this ever aborts.  */
+  len = strlen (msg);
+  if (sizeof buf <= len)
+    abort ();
 
-#endif
+  return memcpy (buf, msg, len + 1);
+}