summaryrefslogtreecommitdiffstats
path: root/lib/libc/string/strerror.c
diff options
context:
space:
mode:
authormike <mike@FreeBSD.org>2002-12-18 16:53:31 +0000
committermike <mike@FreeBSD.org>2002-12-18 16:53:31 +0000
commit91ae3fa45da5b963b386ec2315195c8a46fca992 (patch)
tree16025c382d603596fbc3bf588b0fc5edf45a3c74 /lib/libc/string/strerror.c
parente32cc6fbb43a3952c915a86eefab4195c58aaaf5 (diff)
downloadFreeBSD-src-91ae3fa45da5b963b386ec2315195c8a46fca992.zip
FreeBSD-src-91ae3fa45da5b963b386ec2315195c8a46fca992.tar.gz
Rearrange strerror() so that its itoa procedure can be used with
strerror_r(). Doing this allows us to ensure that strerror_r() always fills the supplied buffer regardless of EINVAL or ERANGE errors. strerror()'s semantics have changed slightly such that an argument of 0 is now considered invalid and errno is set to EINVAL. Remove internal regression test for strerror() and strerror_r(). This will be reincarnated in src/tools/regression/lib/libc/string. In strerror(3), add a comment about strerror()'s bogus return type. PR: 44356
Diffstat (limited to 'lib/libc/string/strerror.c')
-rw-r--r--lib/libc/string/strerror.c124
1 files changed, 39 insertions, 85 deletions
diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c
index 32e35aa..0d2e126 100644
--- a/lib/libc/string/strerror.c
+++ b/lib/libc/string/strerror.c
@@ -37,108 +37,62 @@ static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <errno.h>
#include <stdio.h>
#include <string.h>
-#include <errno.h>
-int
-strerror_r(int errnum, char *strerrbuf, size_t buflen)
-{
- int len;
-
- if ((errnum >= 0) && (errnum < sys_nerr)) {
- len = strlcpy(strerrbuf, (char *)sys_errlist[errnum], buflen);
- return ((len < buflen) ? 0 : ERANGE);
- }
- return (EINVAL);
-}
+#define UPREFIX "Unknown error: "
+/*
+ * Define a buffer size big enough to describe a 64-bit signed integer
+ * converted to ASCII decimal (19 bytes), with an optional leading sign
+ * (1 byte), finally we get the prefix and a trailing NUL from UPREFIX.
+ */
+#define EBUFSIZE (20 + sizeof(UPREFIX))
-char *
-strerror(num)
- int num;
+/* Don't link to stdio(3) to avoid bloat for statically linked binaries. */
+static void
+errstr(int num, char *buf, size_t len)
{
- char *p, *t;
- unsigned int uerr;
- static char const unknown_prefix[] = "Unknown error: ";
-
- /*
- * Define a buffer size big enough to describe a 64-bit
- * number in ASCII decimal (19), with optional leading sign
- * (+1) and trailing NUL (+1).
- */
-# define NUMLEN 21
-# define EBUFLEN (sizeof unknown_prefix + NUMLEN)
- char tmp[NUMLEN]; /* temporary number */
- static char ebuf[EBUFLEN]; /* error message */
-
- if ((num >= 0) && (num < sys_nerr))
- return ((char *)sys_errlist[num]);
+ unsigned int uerr;
+ char *p, *t;
+ char tmp[EBUFSIZE];
- /*
- * Set errno to EINVAL per P1003.1-200x Draft June 14, 2001.
- */
- errno = EINVAL;
-
- /*
- * Print unknown errno by hand so we don't link to stdio(3).
- * This collects the ASCII digits in reverse order.
- */
- uerr = (num > 0) ? num : -num;
+ if (strlcpy(buf, UPREFIX, len) >= len)
+ return;
t = tmp;
+ uerr = (num >= 0) ? num : -num;
do {
*t++ = "0123456789"[uerr % 10];
} while (uerr /= 10);
if (num < 0)
*t++ = '-';
-
- /*
- * Copy the "unknown" message and the number into the caller
- * supplied buffer, inverting the number string.
- */
- strcpy(ebuf, unknown_prefix);
- for (p = ebuf + sizeof unknown_prefix - 1; t > tmp; )
+ for (p = buf + strlen(UPREFIX); t > tmp && p < buf + len - 1;)
*p++ = *--t;
*p = '\0';
- return (ebuf);
}
-#ifdef STANDALONE_TEST
-
-#include <limits.h>
-
-main()
+int
+strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
- char mybuf[64];
- int ret;
-
- errno = 0;
-
- printf("strerror(0) yeilds: %s\n", strerror(0));
- printf("strerror(1) yeilds: %s\n", strerror(1));
- printf("strerror(47) yeilds: %s\n", strerror(47));
- printf("strerror(sys_nerr - 1) yeilds: %s\n", strerror(sys_nerr - 1));
- printf("errno = %d\n", errno); errno = 0;
-
- printf("strerror(sys_nerr) yeilds: %s\n", strerror(sys_nerr));
- printf("errno = %d\n", errno); errno = 0;
-
- printf("strerror(437) yeilds: %s\n", strerror(437));
- printf("errno = %d\n", errno); errno = 0;
-
- printf("strerror(LONG_MAX) yeilds: %s\n", strerror(LONG_MAX));
- printf("strerror(LONG_MIN) yeilds: %s\n", strerror(LONG_MIN));
- printf("strerror(ULONG_MAX) yeilds: %s\n", strerror(ULONG_MAX));
-
- memset(mybuf, '*', 63); mybuf[63] = '\0';
- strerror_r(11, mybuf, 64);
- printf("strerror_r(11) yeilds: %s\n", mybuf);
+ int retval;
+
+ retval = 0;
+ if (errnum < 1 || errnum >= sys_nerr) {
+ errstr(errnum, strerrbuf, buflen);
+ retval = EINVAL;
+ } else if (strlcpy(strerrbuf, sys_errlist[errnum], buflen) >= buflen)
+ retval = ERANGE;
+ return (retval);
+}
- memset(mybuf, '*', 63); mybuf[63] = '\0';
- ret = strerror_r(1234, mybuf, 64);
- printf("strerror_r(1234) returns %d (%s)\n", ret, mybuf);
+char *
+strerror(int num)
+{
+ static char ebuf[EBUFSIZE];
- memset(mybuf, '*', 63); mybuf[63] = '\0';
- ret = strerror_r(1, mybuf, 10);
- printf("strerror_r on short buffer returns %d (%s)\n", ret, mybuf);
+ if (num > 0 && num < sys_nerr)
+ return ((char *)sys_errlist[num]);
+ errno = EINVAL;
+ errstr(num, ebuf, sizeof(ebuf));
+ return (ebuf);
}
-#endif
OpenPOWER on IntegriCloud