1/* strerror.c --- POSIX compatible system error routine
2
3   Copyright (C) 2007-2012 Free Software Foundation, Inc.
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18#include <config.h>
19
20/* Specification.  */
21#include <string.h>
22
23#include <errno.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "intprops.h"
29#include "strerror-override.h"
30#include "verify.h"
31
32/* Use the system functions, not the gnulib overrides in this file.  */
33#undef sprintf
34
35char *
36strerror (int n)
37#undef strerror
38{
39  static char buf[STACKBUF_LEN];
40  size_t len;
41
42  /* Cast away const, due to the historical signature of strerror;
43     callers should not be modifying the string.  */
44  const char *msg = strerror_override (n);
45  if (msg)
46    return (char *) msg;
47
48  msg = strerror (n);
49
50  /* Our strerror_r implementation might use the system's strerror
51     buffer, so all other clients of strerror have to see the error
52     copied into a buffer that we manage.  This is not thread-safe,
53     even if the system strerror is, but portable programs shouldn't
54     be using strerror if they care about thread-safety.  */
55  if (!msg || !*msg)
56    {
57      static char const fmt[] = "Unknown error %d";
58      verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n));
59      sprintf (buf, fmt, n);
60      errno = EINVAL;
61      return buf;
62    }
63
64  /* Fix STACKBUF_LEN if this ever aborts.  */
65  len = strlen (msg);
66  if (sizeof buf <= len)
67    abort ();
68
69  return memcpy (buf, msg, len + 1);
70}
71