195b7b453SJohn Marino /* strerror.c --- POSIX compatible system error routine
295b7b453SJohn Marino
3*09d4459fSDaniel Fojt Copyright (C) 2007-2020 Free Software Foundation, Inc.
495b7b453SJohn Marino
595b7b453SJohn Marino This program is free software: you can redistribute it and/or modify
695b7b453SJohn Marino it under the terms of the GNU General Public License as published by
795b7b453SJohn Marino the Free Software Foundation; either version 3 of the License, or
895b7b453SJohn Marino (at your option) any later version.
995b7b453SJohn Marino
1095b7b453SJohn Marino This program is distributed in the hope that it will be useful,
1195b7b453SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
1295b7b453SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1395b7b453SJohn Marino GNU General Public License for more details.
1495b7b453SJohn Marino
1595b7b453SJohn Marino You should have received a copy of the GNU General Public License
16*09d4459fSDaniel Fojt along with this program. If not, see <https://www.gnu.org/licenses/>. */
1795b7b453SJohn Marino
1895b7b453SJohn Marino #include <config.h>
1995b7b453SJohn Marino
20200fbe8dSJohn Marino /* Specification. */
2195b7b453SJohn Marino #include <string.h>
2295b7b453SJohn Marino
2395b7b453SJohn Marino #include <errno.h>
2495b7b453SJohn Marino #include <stdio.h>
25200fbe8dSJohn Marino #include <stdlib.h>
26200fbe8dSJohn Marino #include <string.h>
2795b7b453SJohn Marino
2895b7b453SJohn Marino #include "intprops.h"
29200fbe8dSJohn Marino #include "strerror-override.h"
30200fbe8dSJohn Marino #include "verify.h"
3195b7b453SJohn Marino
3295b7b453SJohn Marino /* Use the system functions, not the gnulib overrides in this file. */
3395b7b453SJohn Marino #undef sprintf
3495b7b453SJohn Marino
3595b7b453SJohn Marino char *
strerror(int n)36200fbe8dSJohn Marino strerror (int n)
37200fbe8dSJohn Marino #undef strerror
3895b7b453SJohn Marino {
39200fbe8dSJohn Marino static char buf[STACKBUF_LEN];
40200fbe8dSJohn Marino size_t len;
4195b7b453SJohn Marino
42200fbe8dSJohn Marino /* Cast away const, due to the historical signature of strerror;
43200fbe8dSJohn Marino callers should not be modifying the string. */
44200fbe8dSJohn Marino const char *msg = strerror_override (n);
4595b7b453SJohn Marino if (msg)
4695b7b453SJohn Marino return (char *) msg;
4795b7b453SJohn Marino
48200fbe8dSJohn Marino msg = strerror (n);
4995b7b453SJohn Marino
50200fbe8dSJohn Marino /* Our strerror_r implementation might use the system's strerror
51200fbe8dSJohn Marino buffer, so all other clients of strerror have to see the error
52200fbe8dSJohn Marino copied into a buffer that we manage. This is not thread-safe,
53200fbe8dSJohn Marino even if the system strerror is, but portable programs shouldn't
54200fbe8dSJohn Marino be using strerror if they care about thread-safety. */
55200fbe8dSJohn Marino if (!msg || !*msg)
5695b7b453SJohn Marino {
57200fbe8dSJohn Marino static char const fmt[] = "Unknown error %d";
58200fbe8dSJohn Marino verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n));
59200fbe8dSJohn Marino sprintf (buf, fmt, n);
60200fbe8dSJohn Marino errno = EINVAL;
61200fbe8dSJohn Marino return buf;
6295b7b453SJohn Marino }
6395b7b453SJohn Marino
64200fbe8dSJohn Marino /* Fix STACKBUF_LEN if this ever aborts. */
65200fbe8dSJohn Marino len = strlen (msg);
66200fbe8dSJohn Marino if (sizeof buf <= len)
67200fbe8dSJohn Marino abort ();
6895b7b453SJohn Marino
69*09d4459fSDaniel Fojt memcpy (buf, msg, len + 1);
70*09d4459fSDaniel Fojt return buf;
71200fbe8dSJohn Marino }
72