summaryrefslogtreecommitdiffstats
path: root/newlib/libc/string/strerror_r.c
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2011-02-10 16:48:18 +0000
committerEric Blake <eblake@redhat.com>2011-02-10 16:48:18 +0000
commit7c10a76dec8afaf548bf14453ebd689e3457518e (patch)
treec3e235b29e3a74fa8451f5d3f4c79977d0755296 /newlib/libc/string/strerror_r.c
parent27aaf2a9d19de72291d77c45649951738b697f57 (diff)
downloadcygnal-7c10a76dec8afaf548bf14453ebd689e3457518e.tar.gz
cygnal-7c10a76dec8afaf548bf14453ebd689e3457518e.tar.bz2
cygnal-7c10a76dec8afaf548bf14453ebd689e3457518e.zip
strerror_r: provide POSIX implementation
* libc/include/string.h (strerror_r): Update declaration. * libc/string/strerror.c (strerror): Update documentation. * libc/string/strerror_r.c (strerror_r): Always return NUL-terminated string; don't overwrite too-short buf. * libc/string/xpg_strerror_r.c (__xpg_strerror_r): Implement POSIX variant. * libc/string/Makefile.am (GENERAL_SOURCES): Build new file. * libc/string/Makefile.in: Regenerate.
Diffstat (limited to 'newlib/libc/string/strerror_r.c')
-rw-r--r--newlib/libc/string/strerror_r.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/newlib/libc/string/strerror_r.c b/newlib/libc/string/strerror_r.c
index be5358f3e..c2057b7f0 100644
--- a/newlib/libc/string/strerror_r.c
+++ b/newlib/libc/string/strerror_r.c
@@ -1,3 +1,4 @@
+/* GNU variant of strerror_r. */
/*
FUNCTION
<<strerror_r>>---convert error number to string and copy to buffer
@@ -7,7 +8,11 @@ INDEX
ANSI_SYNOPSIS
#include <string.h>
+ #ifdef _GNU_SOURCE
char *strerror_r(int <[errnum]>, char *<[buffer]>, size_t <[n]>);
+ #else
+ int strerror_r(int <[errnum]>, char *<[buffer]>, size_t <[n]>);
+ #endif
TRAD_SYNOPSIS
#include <string.h>
@@ -19,35 +24,60 @@ TRAD_SYNOPSIS
DESCRIPTION
<<strerror_r>> converts the error number <[errnum]> into a
string and copies the result into the supplied <[buffer]> for
-a length up to <[n]>, including the NUL terminator. The value of
-<[errnum]> is usually a copy of <<errno>>. If <<errnum>> is not a known
+a length up to <[n]>, including the NUL terminator. The value of
+<[errnum]> is usually a copy of <<errno>>. If <<errnum>> is not a known
error number, the result is the empty string.
See <<strerror>> for how strings are mapped to <<errnum>>.
RETURNS
-This function returns a pointer to a string. Your application must
-not modify that string.
+There are two variants: the GNU version always returns a NUL-terminated
+string, which is <[buffer]> if all went well, but which is another
+pointer if <[n]> was too small (leaving <[buffer]> untouched). If the
+return is not <[buffer]>, your application must not modify that string.
+The POSIX version returns 0 on success, <[EINVAL]> if <<errnum>> was not
+recognized, and <[ERANGE]> if <[n]> was too small. The variant chosen
+depends on macros that you define before inclusion of <<string.h>>.
PORTABILITY
-<<strerror_r>> is a GNU extension.
+<<strerror_r>> with a <[char *]> result is a GNU extension.
+<<strerror_r>> with an <[int]> result is required by POSIX 2001.
+This function is compliant only if <<_user_strerror>> is not provided,
+or if it is thread-safe and does not modify <<errno>>.
+
+POSIX states that the contents of <[buf]> are unspecified on error,
+although this implementation guarantees a NUL-terminated string for
+all except <[n]> of 0.
+
+POSIX recommends that unknown <[errnum]> result in a message including
+that value, however it is not a requirement and this implementation
+provides only an empty string (unless you provide <<_user_strerror>>).
+POSIX also recommends that unknown <[errnum]> fail with EINVAL even
+when providing such a message, however it is not a requirement and
+this implementation will return success if <<_user_strerror>> provided
+a non-empty alternate string.
<<strerror_r>> requires no supporting OS subroutines.
*/
#undef __STRICT_ANSI__
+#define _GNU_SOURCE
#include <errno.h>
#include <string.h>
+#undef strerror_r
+/* For backwards-compatible linking, this must be the GNU signature;
+ see xpg_strerror_r.c for the POSIX version. */
char *
_DEFUN (strerror_r, (errnum, buffer, n),
int errnum _AND
char *buffer _AND
size_t n)
{
- char *error;
- error = strerror (errnum);
+ char *error = strerror (errnum);
- return strncpy (buffer, (const char *)error, n);
+ if (strlen (error) >= n)
+ return error;
+ return strcpy (buffer, error);
}