freebsd-nq/lib/libc/string/strerror.c
Konstantin Belousov cd49e866fc Bump sys_errlist size to keep ABI backward-compatible for some time.
Addition of the new errno values requires adding new elements to
sys_errlist array, which is actually ABI-incompatible, since ELF
records the object size.  Expand array in advance to 150 elements so
that we have our users to go over the issue only once, at least until
more than 53 new errors are added.

I did not bumped the symbol version, same as it was not done for
previous increases of the array size.  Runtime linker only copies as
much data into binary object on copy relocation as the binary'object
specifies.  This is not fixable for binaries which access sys_errlist
directly.

While there, correct comment and calculation of the temporary buffer
size for the message printed for unknown error.  The on-stack buffer
is used only for the number and delimiter since r108603.

Requested by:	mckusick
Reviewed by:	mckusick, yuripv
MFC after:	2 weeks
Sponsored by:	The FreeBSD Foundation
Differential revision:	https://reviews.freebsd.org/D18656
2018-12-27 13:02:15 +00:00

128 lines
3.4 KiB
C

/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#if defined(NLS)
#include <nl_types.h>
#endif
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include "errlst.h"
/*
* Define buffer big enough to contain delimiter (": ", 2 bytes),
* 64-bit signed integer converted to ASCII decimal (19 bytes) with
* optional leading sign (1 byte), and a trailing NUL.
*/
#define EBUFSIZE (2 + 19 + 1 + 1)
/*
* Doing this by hand instead of linking with stdio(3) avoids bloat for
* statically linked binaries.
*/
static void
errstr(int num, char *uprefix, char *buf, size_t len)
{
char *t;
unsigned int uerr;
char tmp[EBUFSIZE];
t = tmp + sizeof(tmp);
*--t = '\0';
uerr = (num >= 0) ? num : -num;
do {
*--t = "0123456789"[uerr % 10];
} while (uerr /= 10);
if (num < 0)
*--t = '-';
*--t = ' ';
*--t = ':';
strlcpy(buf, uprefix, len);
strlcat(buf, t, len);
}
int
strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
int retval = 0;
#if defined(NLS)
int saved_errno = errno;
nl_catd catd;
catd = catopen("libc", NL_CAT_LOCALE);
#endif
if (errnum < 0 || errnum >= __hidden_sys_nerr) {
errstr(errnum,
#if defined(NLS)
catgets(catd, 1, 0xffff, __uprefix),
#else
__uprefix,
#endif
strerrbuf, buflen);
retval = EINVAL;
} else {
if (strlcpy(strerrbuf,
#if defined(NLS)
catgets(catd, 1, errnum, __hidden_sys_errlist[errnum]),
#else
__hidden_sys_errlist[errnum],
#endif
buflen) >= buflen)
retval = ERANGE;
}
#if defined(NLS)
catclose(catd);
errno = saved_errno;
#endif
return (retval);
}
char *
strerror(int num)
{
static char ebuf[NL_TEXTMAX];
if (strerror_r(num, ebuf, sizeof(ebuf)) != 0)
errno = EINVAL;
return (ebuf);
}