summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/string/strerror.331
-rw-r--r--lib/libc/string/strerror.c119
2 files changed, 78 insertions, 72 deletions
diff --git a/lib/libc/string/strerror.3 b/lib/libc/string/strerror.3
index ed63b25..037b138 100644
--- a/lib/libc/string/strerror.3
+++ b/lib/libc/string/strerror.3
@@ -81,16 +81,7 @@ function renders the same result into
.Fa strerrbuf
for a maximum of
.Fa buflen
-characters and returns 0 upon success. If insufficient
-storage is provided in
-.Fa strerrbuf
-(as specified in
-.Fa buflen )
-to contain the error string,
-.Er ERANGE
-is returned and the string in
-.Fa strerrbuf
-may not be null-terminated.
+characters and returns 0 upon success.
.Pp
The
.Fn perror
@@ -114,9 +105,25 @@ otherwise, only the error message string is printed.
If
.Fa errnum
is not a recognized error number,
-the error message string will contain
+.Fn strerror
+returns an error message string containing
.Dq Li "Unknown error:\ "
-followed by the error number in decimal.
+followed by the error number in decimal, while
+.Fn strerror_r
+returns
+.Er EINVAL .
+.Pp
+If insufficient storage is provided in
+.Fa strerrbuf
+(as specified in
+.Fa buflen )
+to contain the error string,
+.Fn strerror_r
+returns
+.Er ERANGE
+and the contents of
+.Fa strerrbuf
+are indeterminate.
.Pp
The message strings can be accessed directly using the external
array
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