diff options
author | wes <wes@FreeBSD.org> | 2001-11-27 07:39:46 +0000 |
---|---|---|
committer | wes <wes@FreeBSD.org> | 2001-11-27 07:39:46 +0000 |
commit | bdb2c68332b68e36058dc5c28babfde3e25eb657 (patch) | |
tree | b90fb7c1ae21a4aea48bd726dac9ed2e1334e2f1 /lib/libc/string/strerror.c | |
parent | 2181f49061145e58c15976406275f1c9fd4b82f9 (diff) | |
download | FreeBSD-src-bdb2c68332b68e36058dc5c28babfde3e25eb657.zip FreeBSD-src-bdb2c68332b68e36058dc5c28babfde3e25eb657.tar.gz |
Add strerror_r function per Posix prototype.
Reviewed by: Mike Barcroft <mike@FreeBSD.org>
MFC after: 2 weeks
Diffstat (limited to 'lib/libc/string/strerror.c')
-rw-r--r-- | lib/libc/string/strerror.c | 93 |
1 files changed, 74 insertions, 19 deletions
diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c index 626e5d7..8628d8d 100644 --- a/lib/libc/string/strerror.c +++ b/lib/libc/string/strerror.c @@ -39,35 +39,90 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <string.h> +#include <errno.h> -char * -strerror(num) - int num; + +int +strerror_r(int errnum, char *strerrbuf, size_t buflen) { #define UPREFIX "Unknown error: " - static char ebuf[40] = UPREFIX; /* 64-bit number + slop */ - register unsigned int errnum; - register char *p, *t; - char tmp[40]; + unsigned int uerr; + char *p, *t; + char tmp[40]; /* 64-bit number + slop */ + int len; - errnum = num; /* convert to unsigned */ - if (errnum < sys_nerr) - return ((char *)sys_errlist[errnum]); + uerr = errnum; /* convert to unsigned */ + if (uerr < sys_nerr) { + len = strlcpy(strerrbuf, (char *)sys_errlist[uerr], buflen); + return (len <= buflen) ? 0 : ERANGE; + } - /* Do this by hand, so we don't link to stdio(3). */ + /* Print unknown errno by hand so we don't link to stdio(3). */ t = tmp; - if (num < 0) - errnum = -errnum; + if (errnum < 0) + uerr = -uerr; do { - *t++ = "0123456789"[errnum % 10]; - } while (errnum /= 10); - if (num < 0) + *t++ = "0123456789"[uerr % 10]; + } while (uerr /= 10); + + if (errnum < 0) *t++ = '-'; - for (p = ebuf + sizeof(UPREFIX) - 1;;) { + + strlcpy(strerrbuf, UPREFIX, buflen); + for (p = strerrbuf + sizeof(UPREFIX) - 1; p < strerrbuf + buflen; ) { *p++ = *--t; if (t <= tmp) break; } - *p = '\0'; - return (ebuf); + + if (p < strerrbuf + buflen) { + *p = '\0'; + return 0; + } + + return ERANGE; +} + + +/* + * 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; +} + + +#ifdef STANDALONE_TEST +main() +{ + char mybuf[64]; + int ret; + + printf("strerror(47) yeilds: %s\n", strerror(47)); + 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); + printf("strerror_r on short buffer returns %d (%s)\n", ret, mybuf); } +#endif |