summaryrefslogtreecommitdiffstats
path: root/lib/libc/string/strerror.c
diff options
context:
space:
mode:
authorwes <wes@FreeBSD.org>2001-12-06 04:53:31 +0000
committerwes <wes@FreeBSD.org>2001-12-06 04:53:31 +0000
commit9a811aeadbcae64af62451c202a0bb317945a9dc (patch)
tree5e497a3ec40cddc305b92cc007654a2bd8169cbb /lib/libc/string/strerror.c
parent9beed4b8190f3bada01b6b0ea725fbe8d6eb14bd (diff)
downloadFreeBSD-src-9a811aeadbcae64af62451c202a0bb317945a9dc.zip
FreeBSD-src-9a811aeadbcae64af62451c202a0bb317945a9dc.tar.gz
New, improved, more Posix-compliant strerror_r implementation,
complete with documentation. Reviewed by: mike@ gad@ MFC after: 1 week
Diffstat (limited to 'lib/libc/string/strerror.c')
-rw-r--r--lib/libc/string/strerror.c119
1 files changed, 59 insertions, 60 deletions
diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c
index 8628d8d..e0f4cd3 100644
--- a/lib/libc/string/strerror.c
+++ b/lib/libc/string/strerror.c
@@ -41,88 +41,87 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <errno.h>
-
int
strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
-#define UPREFIX "Unknown error: "
- unsigned int uerr;
- char *p, *t;
- char tmp[40]; /* 64-bit number + slop */
- int len;
-
- uerr = errnum; /* convert to unsigned */
- if (uerr < sys_nerr) {
- len = strlcpy(strerrbuf, (char *)sys_errlist[uerr], buflen);
- return (len <= buflen) ? 0 : ERANGE;
+ int len;
+
+ if ((errnum > 0) && (errnum < sys_nerr)) {
+ len = strlcpy(strerrbuf, (char *)sys_errlist[errnum], buflen);
+ return ((len <= buflen) ? 0 : ERANGE);
}
+ return (EINVAL);
+}
- /* Print unknown errno by hand so we don't link to stdio(3). */
+char *
+strerror(num)
+ int num;
+{
+ 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]);
+
+ /*
+ * 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;
t = tmp;
- if (errnum < 0)
- uerr = -uerr;
do {
*t++ = "0123456789"[uerr % 10];
} while (uerr /= 10);
-
- if (errnum < 0)
+ if (num < 0)
*t++ = '-';
- strlcpy(strerrbuf, UPREFIX, buflen);
- for (p = strerrbuf + sizeof(UPREFIX) - 1; p < strerrbuf + buflen; ) {
+ /*
+ * 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; )
*p++ = *--t;
- if (t <= tmp)
- break;
- }
-
- if (p < strerrbuf + buflen) {
- *p = '\0';
- return 0;
- }
-
- return ERANGE;
+ *p = '\0';
+ return (ebuf);
}
+#ifdef STANDALONE_TEST
-/*
- * NOTE: the following length should be enough to hold the longest defined
- * error message in sys_errlist, defined in ../gen/errlst.c. This is a WAG
- * that is better than the previous value.
- */
-#define ERR_LEN 64
-
-char *
-strerror(num)
- int num;
-{
- unsigned int uerr;
- static char ebuf[ERR_LEN];
-
- uerr = num; /* convert to unsigned */
- if (uerr < sys_nerr)
- return (char *)sys_errlist[uerr];
-
- /* strerror can't fail so handle truncation semi-elegantly */
- if (strerror_r(num, ebuf, (size_t) ERR_LEN) != 0)
- ebuf[ERR_LEN - 1] = '\0';
-
- return ebuf;
-}
-
+#include <limits.h>
-#ifdef STANDALONE_TEST
main()
{
- char mybuf[64];
- int ret;
+ char mybuf[64];
+ int ret;
printf("strerror(47) yeilds: %s\n", strerror(47));
+ printf("strerror(437) yeilds: %s\n", strerror(437));
+ 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);
- strerror_r(1234, mybuf, 64);
- printf("strerror_r(1234) yeilds: %s\n", mybuf);
- memset(mybuf, '*', 63);
- ret = strerror_r(4321, mybuf, 16);
+
+ memset(mybuf, '*', 63); mybuf[63] = '\0';
+ ret = strerror_r(1234, mybuf, 64);
+ printf("strerror_r(1234) returns %d (%s)\n", ret, mybuf);
+
+ memset(mybuf, '*', 63); mybuf[63] = '\0';
+ ret = strerror_r(1, mybuf, 10);
printf("strerror_r on short buffer returns %d (%s)\n", ret, mybuf);
}
#endif
OpenPOWER on IntegriCloud