1 /* strerror_r.c --- POSIX compatible system error routine
3 Copyright (C) 2010-2011 Free Software Foundation, Inc.
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.
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.
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/>. */
18 /* Written by Bruno Haible <bruno@clisp.org>, 2010. */
27 #if HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__) && !EXTEND_STRERROR_R
29 /* The system's strerror_r function is OK, except that its third argument
30 is 'int', not 'size_t'. */
35 strerror_r (int errnum, char *buf, size_t buflen)
44 /* On HP-UX 11.31, strerror_r always fails when buflen < 80. */
48 if (buflen < sizeof (stackbuf))
50 ret = strerror_r (errnum, stackbuf, sizeof (stackbuf));
53 size_t len = strlen (stackbuf);
56 memcpy (buf, stackbuf, len + 1);
62 ret = strerror_r (errnum, buf, buflen);
65 ret = strerror_r (errnum, buf, buflen);
69 /* On AIX 6.1, strerror_r returns -1 and sets errno to EINVAL
71 if (ret < 0 && errno == EINVAL && buflen <= 1)
73 /* Retry with a larger buffer. */
75 ret = strerror_r (errnum, largerbuf, sizeof (largerbuf));
76 if (ret < 0 && errno == EINVAL)
78 /* errnum was out of range. */
83 /* buf was too small. */
89 /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
90 return (ret < 0 ? errno : ret);
93 #elif (__GLIBC__ >= 2 || defined __UCLIBC__) && HAVE___XPG_STRERROR_R /* glibc >= 2.3.4 */ && !EXTEND_STRERROR_R
96 strerror_r (int errnum, char *buf, size_t buflen)
98 extern int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
100 int ret = __xpg_strerror_r (errnum, buf, buflen);
101 return (ret < 0 ? errno : ret);
104 #else /* (__GLIBC__ >= 2 || defined __UCLIBC__ ? !HAVE___XPG_STRERROR_R : !HAVE_DECL_STRERROR_R) || EXTEND_STRERROR_R */
106 # include "glthread/lock.h"
108 /* Use strerror(), with locking. */
110 /* This lock protects the buffer returned by strerror(). We assume that
111 no other uses of strerror() exist in the program. */
112 gl_lock_define_initialized(static, strerror_lock)
115 strerror_r (int errnum, char *buf, size_t buflen)
117 gl_lock_lock (strerror_lock);
120 char *errmsg = strerror (errnum);
121 size_t len = strlen (errmsg);
126 memcpy (buf, errmsg, len + 1);
132 gl_lock_unlock (strerror_lock);