Преглед на файлове

Attempt to clean up the strerror_r situation.

Manuel Novoa III преди 22 години
родител
ревизия
b815b84a59
променени са 8 файла, в които са добавени 402 реда и са изтрити 333 реда
  1. 23 4
      include/string.h
  2. 1 1
      libc/stdio/old_vfprintf.c
  3. 1 1
      libc/stdio/printf.c
  4. 2 36
      libc/stdio/stdio.c
  5. 0 133
      libc/string/strerror.c
  6. 0 140
      libc/string/sys_errlist.c
  7. 375 10
      libc/string/wstring.c
  8. 0 8
      libc/sysdeps/linux/common/bits/uClibc_stdio.h

+ 23 - 4
include/string.h

@@ -232,10 +232,29 @@ extern size_t strnlen (__const char *__string, size_t __maxlen)
 
 /* Return a string describing the meaning of the `errno' code in ERRNUM.  */
 extern char *strerror (int __errnum) __THROW;
-#ifdef	__USE_MISC
-/* Reentrant version of `strerror'.  If a temporary buffer is required, at
-   most BUFLEN bytes of BUF will be used.  */
-extern int strerror_r (int __errnum, char *__buf, size_t buflen) __THROW;
+
+/* Reentrant versions of `strerror'.  If a temporary buffer is required,
+   at most BUFLEN bytes of BUF will be used.  These symbols are _NOT_ intended
+   to be applications, and can change at any time. */
+extern char *_glibc_strerror_r (int __errnum, char *__buf, size_t __buflen) __THROW;
+extern int _susv3_strerror_r (int __errnum, char *__buf, size_t buflen) __THROW;
+
+#if defined(__USE_XOPEN2K) && !defined(__USE_GNU)
+# ifdef __REDIRECT
+extern int __REDIRECT (strerror_r,
+                       (int __errnum, char *__buf, size_t buflen) __THROW,
+                       _susv3_strerror_r);
+# else
+#  define strerror_r _susv3_strerror_r
+# endif
+#elif defined(__USE_MISC)
+# ifdef __REDIRECT
+extern char *__REDIRECT (strerror_r,
+                         (int __errnum, char *__buf, size_t buflen) __THROW,
+                         _glibc_strerror_r);
+# else
+#  define strerror_r _glibc_strerror_r
+# endif
 #endif
 
 /* We define this function always since `bzero' is sometimes needed when

+ 1 - 1
libc/stdio/old_vfprintf.c

@@ -272,7 +272,7 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
 			if (*fmt == 'm') {
 				flag[FLAG_PLUS] = '\0';
 				flag[FLAG_0_PAD] = ' ';
-				p = _stdio_strerror_r(errno, tmp, sizeof(tmp));
+				p = _glibc_strerror_r(errno, tmp, sizeof(tmp));
 				goto print;
 			}
 #endif

+ 1 - 1
libc/stdio/printf.c

@@ -1220,7 +1220,7 @@ int _do_one_spec(FILE * __restrict stream, register ppfs_t *ppfs, int *count)
 			}
 #ifdef __STDIO_PRINTF_M_SUPPORT
 		} else if (ppfs->conv_num == CONV_m) {
-			s = _stdio_strerror_r(errno, buf, sizeof(buf));
+			s = _glibc_strerror_r(errno, buf, sizeof(buf));
 			goto SET_STRING_LEN;
 #endif
 		} else {

+ 2 - 36
libc/stdio/stdio.c

@@ -3218,7 +3218,7 @@ void perror(register const char *s)
 	{
 		char buf[64];
 		fprintf(stderr, "%s%s%s\n", s, sep,
-				_stdio_strerror_r(errno, buf, sizeof(buf)));
+				_glibc_strerror_r(errno, buf, sizeof(buf)));
 	}
 #endif
 #else
@@ -3228,7 +3228,7 @@ void perror(register const char *s)
 
 		__STDIO_THREADLOCK(stderr);
 		_stdio_fdout(STDERR_FILENO, s, sep,
-					 _stdio_strerror_r(errno, buf, sizeof(buf)));
+					 _glibc_strerror_r(errno, buf, sizeof(buf)));
 		__STDIO_THREADUNLOCK(stderr);
 	}
 #endif
@@ -3328,37 +3328,3 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
 
 #endif
 /**********************************************************************/
-#ifdef L__stdio_strerror_r
-
-/* This is an internal routine, and assumes buf and buflen are set
- * appropriately.
- * 
- * WARNING!!! While it is similar to the glibc strerror_r function,
- * it is not the same.  It is expected that "unknown" error strings
- * will fit in the buffer passed.  Also, the return value may not
- * be == buf, as unknown strings are "right-justified" in the buf
- * due to the way _int10stostr works. */
-
-static const char unknown[] = "Unknown error";
-
-char *_stdio_strerror_r(int err, register char *buf, size_t buflen)
-{
-	int errsave;
-
-	assert(buflen >= __UIM_BUFLEN_INT + sizeof(unknown));
-
-	errsave = errno;			/* Backup the errno. */
-
-	if (strerror_r(err, buf, buflen)) {	/* Failed! */
-		__set_errno(errsave);	/* Restore old errno. */
-
-		buf = _int10tostr(buf+buflen-1, err) - sizeof(unknown);
-		strcpy(buf, unknown);
-		buf[sizeof(unknown)-1] = ' '; /* Overwrite the nul. */
-	}
-
-	return buf;
-}
-
-#endif
-/**********************************************************************/

+ 0 - 133
libc/string/strerror.c

@@ -1,133 +0,0 @@
-/* Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-/*
- * Manuel Novoa III       Dec 2000
- *
- * Converted to use my new (un)signed long (long) to string routines, which
- * are smaller than the previous functions and don't require static buffers.
- * Removed dependence on strcat in the process.
- *
- * Also appended a test routine ( -DCHECK_BUF ) to allow a quick check
- * on the buffer length when the sys_errorlist is modified.
- *
- * Added the option WANT_ERRORLIST for low-memory applications to omit the
- * error message strings and only output the error number.
- *
- * Manuel Novoa III       Feb 2002
- *
- * Change to _int10tostr and fix a bug in end-of-buf arg.
- *
- * Erik Andersen          June 2002
- *
- * Added strerror_r (per SuSv3 which differs from glibc) and adapted
- * strerror to match.
- */
-
-#define WANT_ERRORLIST     1
-
-#define _STDIO_UTILITY			/* For _int10tostr. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-int strerror_r(int err, char *retbuf, size_t buflen)
-{
-#if WANT_ERRORLIST
-    if (err < 0 ||  err >= sys_nerr || sys_errlist[err] == NULL) {
-	return -EINVAL;
-    }
-    if (retbuf==NULL || buflen < 1) {
-	return -ERANGE;
-    }
-    strncpy(retbuf, sys_errlist[err], buflen);
-    retbuf[buflen-1] = '\0';
-    return 0;
-#else
-    char *pos;
-    static const char unknown_error[] = "Unknown Error: errno"; /* = */
-
-    if (err < 0 ||  err >= sys_nerr || sys_errlist[err] == NULL) {
-	return -EINVAL;
-    }
-    /* unknown error -- leave space for the '=' */
-    pos = _int10tostr(retbuf+sizeof(retbuf)-1, err) - sizeof(unknown_error);
-    strcpy(pos, unknown_error);
-    *(pos + sizeof(unknown_error) - 1) = '=';
-    return 0;
-#endif
-}
-
-/* Return a string descibing the errno code in ERRNUM.
-   The storage is good only until the next call to strerror.
-   Writing to the storage causes undefined behavior.  */
-char *strerror(int err)
-{
-#if WANT_ERRORLIST
-    static char retbuf[48];
-#else
-#if __BUFLEN_INT10TOSTR > 12
-#error currently set up for 32 bit ints max!
-#endif
-    static char retbuf[33];			/* 33 is sufficient for 32 bit ints */
-#endif
-    
-    if (strerror_r(err, retbuf, sizeof(retbuf)) != 0) {
-	return NULL;
-    }
-    return(retbuf);
-}
-
-#ifdef CHECK_BUF
-/* quick way to check buffer length */
-#include <stdio.h>
-#include <stdlib.h>
-int main(void)
-{
-	int max = 0;
-	int j, retcode;
-	char *p;
-#if WANT_ERRORLIST
-	int i;
-#endif
-
-	retcode = EXIT_SUCCESS;
-
-#if WANT_ERRORLIST
-	for ( i=0 ; i < sys_nerr ; i++ ) {
-		j = strlen(sys_errlist[i])+1;
-		if (j > max) max = j;
-	}
-#endif
-
-	p = strerror(INT_MIN);
-	j = retbuf+sizeof(retbuf) - p;
-	if ( > max) {
-	    max = j;
-	    printf("strerror.c - Test of INT_MIN: <%s>  %d\n", p, j);
-	}
-
-	if (sizeof(retbuf) != max) {
-		printf("Error: strerror.c - dimension of retbuf should be = %d\n", max);
-		retcode = EXIT_FAILURE;
-	}
-	printf("Passed.\n");
-
-	return retcode;
-}
-#endif

+ 0 - 140
libc/string/sys_errlist.c

@@ -1,140 +0,0 @@
-#include <stddef.h>
-#if 0
-#include <errno.h>
-#endif
-
-/* This is a list of all known signal numbers.  */
-
-const char * const sys_errlist[] = {
-	"Success",				/* 0 */
-	"Operation not permitted", 		/* EPERM */
-	"No such file or directory", 		/* ENOENT */
-	"No such process", 			/* ESRCH */
-	"Interrupted system call", 		/* EINTR */
-	"I/O error", 				/* EIO */
-	"No such device or address", 		/* ENXIO */
-	"Arg list too long", 			/* E2BIG */
-	"Exec format error", 			/* ENOEXEC */
-	"Bad file number", 			/* EBADF */
-	"No child processes", 			/* ECHILD */
-	"Try again", 				/* EAGAIN */
-	"Out of memory", 			/* ENOMEM */
-	"Permission denied", 			/* EACCES */
-	"Bad address", 				/* EFAULT */
-	"Block device required", 		/* ENOTBLK */
-	"Device or resource busy", 		/* EBUSY */
-	"File exists", 				/* EEXIST */
-	"Cross-device link", 			/* EXDEV */
-	"No such device", 			/* ENODEV */
-	"Not a directory", 			/* ENOTDIR */
-	"Is a directory", 			/* EISDIR */
-	"Invalid argument", 			/* EINVAL */
-	"File table overflow", 			/* ENFILE */
-	"Too many open files", 			/* EMFILE */
-	"Not a typewriter", 			/* ENOTTY */
-	"Text file busy", 			/* ETXTBSY */
-	"File too large", 			/* EFBIG */
-	"No space left on device", 		/* ENOSPC */
-	"Illegal seek", 			/* ESPIPE */
-	"Read-only file system", 		/* EROFS */
-	"Too many links", 			/* EMLINK */
-	"Broken pipe", 				/* EPIPE */
-	"Math argument out of domain of func", 	/* EDOM */
-	"Math result not representable", 	/* ERANGE */
-	"Resource deadlock would occur", 	/* EDEADLK */
-	"File name too long", 			/* ENAMETOOLONG */
-	"No record locks available", 		/* ENOLCK */
-	"Function not implemented", 		/* ENOSYS */
-	"Directory not empty", 			/* ENOTEMPTY */
-	"Too many symbolic links encountered", 	/* ELOOP */
-	"Operation would block", 		/* EWOULDBLOCK */
-	"No message of desired type", 		/* ENOMSG */
-	"Identifier removed", 			/* EIDRM */
-	"Channel number out of range", 		/* ECHRNG */
-	"Level 2 not synchronized", 		/* EL2NSYNC */
-	"Level 3 halted", 			/* EL3HLT */
-	"Level 3 reset", 			/* EL3RST */
-	"Link number out of range", 		/* ELNRNG */
-	"Protocol driver not attached", 	/* EUNATCH */
-	"No CSI structure available", 		/* ENOCSI */
-	"Level 2 halted", 			/* EL2HLT */
-	"Invalid exchange", 			/* EBADE */
-	"Invalid request descriptor", 		/* EBADR */
-	"Exchange full", 			/* EXFULL */
-	"No anode", 				/* ENOANO */
-	"Invalid request code", 		/* EBADRQC */
-	"Invalid slot", 			/* EBADSLT */
-	"File locking deadlock error", 		/* EDEADLOCK */
-	"Bad font file format", 		/* EBFONT */
-	"Device not a stream", 			/* ENOSTR */
-	"No data available", 			/* ENODATA */
-	"Timer expired", 			/* ETIME */
-	"Out of streams resources", 		/* ENOSR */
-	"Machine is not on the network", 	/* ENONET */
-	"Package not installed", 		/* ENOPKG */
-	"Object is remote", 			/* EREMOTE */
-	"Link has been severed", 		/* ENOLINK */
-	"Advertise error", 			/* EADV */
-	"Srmount error", 			/* ESRMNT */
-	"Communication error on send", 		/* ECOMM */
-	"Protocol error", 			/* EPROTO */
-	"Multihop attempted", 			/* EMULTIHOP */
-	"RFS specific error", 			/* EDOTDOT */
-	"Not a data message", 			/* EBADMSG */
-	"Value too large for defined data type", 	/* EOVERFLOW */
-	"Name not unique on network", 		/* ENOTUNIQ */
-	"File descriptor in bad state", 	/* EBADFD */
-	"Remote address changed", 		/* EREMCHG */
-	"Can not access a needed shared library", 	/* ELIBACC */
-	"Accessing a corrupted shared library", 	/* ELIBBAD */
-	".lib section in a.out corrupted", 	/* ELIBSCN */
-	"Attempting to link in too many shared libraries", 	/* ELIBMAX */
-	"Cannot exec a shared library directly", 	/* ELIBEXEC */
-	"Illegal byte sequence", 		/* EILSEQ */
-	"Interrupted system call should be restarted", 	/* ERESTART */
-	"Streams pipe error", 			/* ESTRPIPE */
-	"Too many users", 			/* EUSERS */
-	"Socket operation on non-socket", 	/* ENOTSOCK */
-	"Destination address required", 	/* EDESTADDRREQ */
-	"Message too long", 			/* EMSGSIZE */
-	"Protocol wrong type for socket", 	/* EPROTOTYPE */
-	"Protocol not available", 		/* ENOPROTOOPT */
-	"Protocol not supported", 		/* EPROTONOSUPPORT */
-	"Socket type not supported", 		/* ESOCKTNOSUPPORT */
-	"Operation not supported on transport endpoint", 	/* EOPNOTSUPP */
-	"Protocol family not supported", 	/* EPFNOSUPPORT */
-	"Address family not supported by protocol", 	/* EAFNOSUPPORT */
-	"Address already in use", 		/* EADDRINUSE */
-	"Cannot assign requested address", 	/* EADDRNOTAVAIL */
-	"Network is down", 			/* ENETDOWN */
-	"Network is unreachable", 		/* ENETUNREACH */
-	"Network dropped connection because of reset", 	/* ENETRESET */
-	"Software caused connection abort", 	/* ECONNABORTED */
-	"Connection reset by peer", 		/* ECONNRESET */
-	"No buffer space available", 		/* ENOBUFS */
-	"Transport endpoint is already connected", 	/* EISCONN */
-	"Transport endpoint is not connected", 	/* ENOTCONN */
-	"Cannot send after transport endpoint shutdown", 	/* ESHUTDOWN */
-	"Too many references: cannot splice", 	/* ETOOMANYREFS */
-	"Connection timed out", 		/* ETIMEDOUT */
-	"Connection refused", 			/* ECONNREFUSED */
-	"Host is down", 			/* EHOSTDOWN */
-	"No route to host", 			/* EHOSTUNREACH */
-	"Operation already in progress", 	/* EALREADY */
-	"Operation now in progress", 		/* EINPROGRESS */
-	"Stale NFS file handle", 		/* ESTALE */
-	"Structure needs cleaning", 		/* EUCLEAN */
-	"Not a XENIX named type file", 		/* ENOTNAM */
-	"No XENIX semaphores available", 	/* ENAVAIL */
-	"Is a named type file", 		/* EISNAM */
-	"Remote I/O error", 			/* EREMOTEIO */
-	"Quota exceeded", 			/* EDQUOT */
-	"No medium found",			/* ENOMEDIUM */
-	"Wrong medium type",			/* EMEDIUMTYPE */
-	NULL
-};
-
-
-#define NR_ERRORS ((sizeof (sys_errlist))/(sizeof(char *))-1)
-
-const int sys_nerr = NR_ERRORS;

+ 375 - 10
libc/string/wstring.c

@@ -26,12 +26,15 @@
  *
  *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
 
+#define _STDIO_UTILITY
 #define _GNU_SOURCE
 #include <string.h>
 #include <strings.h>
+#include <stdio.h>
 #include <limits.h>
 #include <ctype.h>
 #include <stdlib.h>
+#include <errno.h>
 
 #ifdef WANT_WIDE
 #include <wchar.h>
@@ -53,6 +56,291 @@ typedef unsigned char	__string_uchar_t;
 
 #endif
 
+/**********************************************************************/
+/* NOTE: If we ever do internationalized syserr messages, this will
+ * have to be changed! */
+
+#if _SYS_ERRMSG_MAXLEN < __UIM_BUFLEN_INT + 14
+#define _STRERROR_BUFSIZE (__UIM_BUFLEN_INT + 14)
+#else
+#define _STRERROR_BUFSIZE _SYS_ERRMSG_MAXLEN
+#endif
+
+#define _SYS_NERR		125
+#define _SYS_ERRMSG_MAXLEN	 50
+
+extern const char _string_syserrmsgs[];
+
+/**********************************************************************/
+#ifdef L__string_syserrmsgs
+
+const char _string_syserrmsgs[] = {
+	/*   0:    0,  8 */ "Success\0"
+	/*   1:    8, 24 */ "Operation not permitted\0"
+	/*   2:   32, 26 */ "No such file or directory\0"
+	/*   3:   58, 16 */ "No such process\0"
+	/*   4:   74, 24 */ "Interrupted system call\0"
+	/*   5:   98, 19 */ "Input/output error\0"
+	/*   6:  117, 26 */ "No such device or address\0"
+	/*   7:  143, 23 */ "Argument list too long\0"
+	/*   8:  166, 18 */ "Exec format error\0"
+	/*   9:  184, 20 */ "Bad file descriptor\0"
+	/*  10:  204, 19 */ "No child processes\0"
+	/*  11:  223, 33 */ "Resource temporarily unavailable\0"
+	/*  12:  256, 23 */ "Cannot allocate memory\0"
+	/*  13:  279, 18 */ "Permission denied\0"
+	/*  14:  297, 12 */ "Bad address\0"
+	/*  15:  309, 22 */ "Block device required\0"
+	/*  16:  331, 24 */ "Device or resource busy\0"
+	/*  17:  355, 12 */ "File exists\0"
+	/*  18:  367, 26 */ "Invalid cross-device link\0"
+	/*  19:  393, 15 */ "No such device\0"
+	/*  20:  408, 16 */ "Not a directory\0"
+	/*  21:  424, 15 */ "Is a directory\0"
+	/*  22:  439, 17 */ "Invalid argument\0"
+	/*  23:  456, 30 */ "Too many open files in system\0"
+	/*  24:  486, 20 */ "Too many open files\0"
+	/*  25:  506, 31 */ "Inappropriate ioctl for device\0"
+	/*  26:  537, 15 */ "Text file busy\0"
+	/*  27:  552, 15 */ "File too large\0"
+	/*  28:  567, 24 */ "No space left on device\0"
+	/*  29:  591, 13 */ "Illegal seek\0"
+	/*  30:  604, 22 */ "Read-only file system\0"
+	/*  31:  626, 15 */ "Too many links\0"
+	/*  32:  641, 12 */ "Broken pipe\0"
+	/*  33:  653, 33 */ "Numerical argument out of domain\0"
+	/*  34:  686, 30 */ "Numerical result out of range\0"
+	/*  35:  716, 26 */ "Resource deadlock avoided\0"
+	/*  36:  742, 19 */ "File name too long\0"
+	/*  37:  761, 19 */ "No locks available\0"
+	/*  38:  780, 25 */ "Function not implemented\0"
+	/*  39:  805, 20 */ "Directory not empty\0"
+	/*  40:  825, 34 */ "Too many levels of symbolic links\0"
+	/*  41:  859,  1 */ "\0"
+	/*  42:  860, 27 */ "No message of desired type\0"
+	/*  43:  887, 19 */ "Identifier removed\0"
+	/*  44:  906, 28 */ "Channel number out of range\0"
+	/*  45:  934, 25 */ "Level 2 not synchronized\0"
+	/*  46:  959, 15 */ "Level 3 halted\0"
+	/*  47:  974, 14 */ "Level 3 reset\0"
+	/*  48:  988, 25 */ "Link number out of range\0"
+	/*  49: 1013, 29 */ "Protocol driver not attached\0"
+	/*  50: 1042, 27 */ "No CSI structure available\0"
+	/*  51: 1069, 15 */ "Level 2 halted\0"
+	/*  52: 1084, 17 */ "Invalid exchange\0"
+	/*  53: 1101, 27 */ "Invalid request descriptor\0"
+	/*  54: 1128, 14 */ "Exchange full\0"
+	/*  55: 1142,  9 */ "No anode\0"
+	/*  56: 1151, 21 */ "Invalid request code\0"
+	/*  57: 1172, 13 */ "Invalid slot\0"
+	/*  58: 1185,  1 */ "\0"
+	/*  59: 1186, 21 */ "Bad font file format\0"
+	/*  60: 1207, 20 */ "Device not a stream\0"
+	/*  61: 1227, 18 */ "No data available\0"
+	/*  62: 1245, 14 */ "Timer expired\0"
+	/*  63: 1259, 25 */ "Out of streams resources\0"
+	/*  64: 1284, 30 */ "Machine is not on the network\0"
+	/*  65: 1314, 22 */ "Package not installed\0"
+	/*  66: 1336, 17 */ "Object is remote\0"
+	/*  67: 1353, 22 */ "Link has been severed\0"
+	/*  68: 1375, 16 */ "Advertise error\0"
+	/*  69: 1391, 14 */ "Srmount error\0"
+	/*  70: 1405, 28 */ "Communication error on send\0"
+	/*  71: 1433, 15 */ "Protocol error\0"
+	/*  72: 1448, 19 */ "Multihop attempted\0"
+	/*  73: 1467, 19 */ "RFS specific error\0"
+	/*  74: 1486, 12 */ "Bad message\0"
+	/*  75: 1498, 38 */ "Value too large for defined data type\0"
+	/*  76: 1536, 27 */ "Name not unique on network\0"
+	/*  77: 1563, 29 */ "File descriptor in bad state\0"
+	/*  78: 1592, 23 */ "Remote address changed\0"
+	/*  79: 1615, 39 */ "Can not access a needed shared library\0"
+	/*  80: 1654, 37 */ "Accessing a corrupted shared library\0"
+	/*  81: 1691, 32 */ ".lib section in a.out corrupted\0"
+	/*  82: 1723, 48 */ "Attempting to link in too many shared libraries\0"
+	/*  83: 1771, 38 */ "Cannot exec a shared library directly\0"
+	/*  84: 1809, 50 */ "Invalid or incomplete multibyte or wide character\0"
+	/*  85: 1859, 44 */ "Interrupted system call should be restarted\0"
+	/*  86: 1903, 19 */ "Streams pipe error\0"
+	/*  87: 1922, 15 */ "Too many users\0"
+	/*  88: 1937, 31 */ "Socket operation on non-socket\0"
+	/*  89: 1968, 29 */ "Destination address required\0"
+	/*  90: 1997, 17 */ "Message too long\0"
+	/*  91: 2014, 31 */ "Protocol wrong type for socket\0"
+	/*  92: 2045, 23 */ "Protocol not available\0"
+	/*  93: 2068, 23 */ "Protocol not supported\0"
+	/*  94: 2091, 26 */ "Socket type not supported\0"
+	/*  95: 2117, 24 */ "Operation not supported\0"
+	/*  96: 2141, 30 */ "Protocol family not supported\0"
+	/*  97: 2171, 41 */ "Address family not supported by protocol\0"
+	/*  98: 2212, 23 */ "Address already in use\0"
+	/*  99: 2235, 32 */ "Cannot assign requested address\0"
+	/* 100: 2267, 16 */ "Network is down\0"
+	/* 101: 2283, 23 */ "Network is unreachable\0"
+	/* 102: 2306, 36 */ "Network dropped connection on reset\0"
+	/* 103: 2342, 33 */ "Software caused connection abort\0"
+	/* 104: 2375, 25 */ "Connection reset by peer\0"
+	/* 105: 2400, 26 */ "No buffer space available\0"
+	/* 106: 2426, 40 */ "Transport endpoint is already connected\0"
+	/* 107: 2466, 36 */ "Transport endpoint is not connected\0"
+	/* 108: 2502, 46 */ "Cannot send after transport endpoint shutdown\0"
+	/* 109: 2548, 35 */ "Too many references: cannot splice\0"
+	/* 110: 2583, 21 */ "Connection timed out\0"
+	/* 111: 2604, 19 */ "Connection refused\0"
+	/* 112: 2623, 13 */ "Host is down\0"
+	/* 113: 2636, 17 */ "No route to host\0"
+	/* 114: 2653, 30 */ "Operation already in progress\0"
+	/* 115: 2683, 26 */ "Operation now in progress\0"
+	/* 116: 2709, 22 */ "Stale NFS file handle\0"
+	/* 117: 2731, 25 */ "Structure needs cleaning\0"
+	/* 118: 2756, 28 */ "Not a XENIX named type file\0"
+	/* 119: 2784, 30 */ "No XENIX semaphores available\0"
+	/* 120: 2814, 21 */ "Is a named type file\0"
+	/* 121: 2835, 17 */ "Remote I/O error\0"
+	/* 122: 2852, 20 */ "Disk quota exceeded\0"
+	/* 123: 2872, 16 */ "No medium found\0"
+	/* 124: 2888, 18 */ "Wrong medium type"
+};
+
+#endif
+/**********************************************************************/
+#ifdef L_sys_errlist
+
+link_warning(_sys_errlist, "sys_nerr and sys_errlist are obsolete and uClibc support for them (in at least some configurations) will probably be unavailable in the near future.")
+
+int sys_nerr = _SYS_NERR;
+
+const char *const sys_errlist[] = {
+	_string_syserrmsgs + 0,
+	_string_syserrmsgs + 8,
+	_string_syserrmsgs + 32,
+	_string_syserrmsgs + 58,
+	_string_syserrmsgs + 74,
+	_string_syserrmsgs + 98,
+	_string_syserrmsgs + 117,
+	_string_syserrmsgs + 143,
+	_string_syserrmsgs + 166,
+	_string_syserrmsgs + 184,
+	_string_syserrmsgs + 204,
+	_string_syserrmsgs + 223,
+	_string_syserrmsgs + 256,
+	_string_syserrmsgs + 279,
+	_string_syserrmsgs + 297,
+	_string_syserrmsgs + 309,
+	_string_syserrmsgs + 331,
+	_string_syserrmsgs + 355,
+	_string_syserrmsgs + 367,
+	_string_syserrmsgs + 393,
+	_string_syserrmsgs + 408,
+	_string_syserrmsgs + 424,
+	_string_syserrmsgs + 439,
+	_string_syserrmsgs + 456,
+	_string_syserrmsgs + 486,
+	_string_syserrmsgs + 506,
+	_string_syserrmsgs + 537,
+	_string_syserrmsgs + 552,
+	_string_syserrmsgs + 567,
+	_string_syserrmsgs + 591,
+	_string_syserrmsgs + 604,
+	_string_syserrmsgs + 626,
+	_string_syserrmsgs + 641,
+	_string_syserrmsgs + 653,
+	_string_syserrmsgs + 686,
+	_string_syserrmsgs + 716,
+	_string_syserrmsgs + 742,
+	_string_syserrmsgs + 761,
+	_string_syserrmsgs + 780,
+	_string_syserrmsgs + 805,
+	_string_syserrmsgs + 825,
+	/*  	_string_syserrmsgs + 859, */
+	NULL,						/* glibc compatiblity :-( */
+	_string_syserrmsgs + 860,
+	_string_syserrmsgs + 887,
+	_string_syserrmsgs + 906,
+	_string_syserrmsgs + 934,
+	_string_syserrmsgs + 959,
+	_string_syserrmsgs + 974,
+	_string_syserrmsgs + 988,
+	_string_syserrmsgs + 1013,
+	_string_syserrmsgs + 1042,
+	_string_syserrmsgs + 1069,
+	_string_syserrmsgs + 1084,
+	_string_syserrmsgs + 1101,
+	_string_syserrmsgs + 1128,
+	_string_syserrmsgs + 1142,
+	_string_syserrmsgs + 1151,
+	_string_syserrmsgs + 1172,
+	/*  	_string_syserrmsgs + 1185, */
+	NULL,						/* glibc compatiblity :-( */
+	_string_syserrmsgs + 1186,
+	_string_syserrmsgs + 1207,
+	_string_syserrmsgs + 1227,
+	_string_syserrmsgs + 1245,
+	_string_syserrmsgs + 1259,
+	_string_syserrmsgs + 1284,
+	_string_syserrmsgs + 1314,
+	_string_syserrmsgs + 1336,
+	_string_syserrmsgs + 1353,
+	_string_syserrmsgs + 1375,
+	_string_syserrmsgs + 1391,
+	_string_syserrmsgs + 1405,
+	_string_syserrmsgs + 1433,
+	_string_syserrmsgs + 1448,
+	_string_syserrmsgs + 1467,
+	_string_syserrmsgs + 1486,
+	_string_syserrmsgs + 1498,
+	_string_syserrmsgs + 1536,
+	_string_syserrmsgs + 1563,
+	_string_syserrmsgs + 1592,
+	_string_syserrmsgs + 1615,
+	_string_syserrmsgs + 1654,
+	_string_syserrmsgs + 1691,
+	_string_syserrmsgs + 1723,
+	_string_syserrmsgs + 1771,
+	_string_syserrmsgs + 1809,
+	_string_syserrmsgs + 1859,
+	_string_syserrmsgs + 1903,
+	_string_syserrmsgs + 1922,
+	_string_syserrmsgs + 1937,
+	_string_syserrmsgs + 1968,
+	_string_syserrmsgs + 1997,
+	_string_syserrmsgs + 2014,
+	_string_syserrmsgs + 2045,
+	_string_syserrmsgs + 2068,
+	_string_syserrmsgs + 2091,
+	_string_syserrmsgs + 2117,
+	_string_syserrmsgs + 2141,
+	_string_syserrmsgs + 2171,
+	_string_syserrmsgs + 2212,
+	_string_syserrmsgs + 2235,
+	_string_syserrmsgs + 2267,
+	_string_syserrmsgs + 2283,
+	_string_syserrmsgs + 2306,
+	_string_syserrmsgs + 2342,
+	_string_syserrmsgs + 2375,
+	_string_syserrmsgs + 2400,
+	_string_syserrmsgs + 2426,
+	_string_syserrmsgs + 2466,
+	_string_syserrmsgs + 2502,
+	_string_syserrmsgs + 2548,
+	_string_syserrmsgs + 2583,
+	_string_syserrmsgs + 2604,
+	_string_syserrmsgs + 2623,
+	_string_syserrmsgs + 2636,
+	_string_syserrmsgs + 2653,
+	_string_syserrmsgs + 2683,
+	_string_syserrmsgs + 2709,
+	_string_syserrmsgs + 2731,
+	_string_syserrmsgs + 2756,
+	_string_syserrmsgs + 2784,
+	_string_syserrmsgs + 2814,
+	_string_syserrmsgs + 2835,
+	_string_syserrmsgs + 2852,
+	_string_syserrmsgs + 2872,
+	_string_syserrmsgs + 2888,
+};
+
+#endif
 /**********************************************************************/
 #ifdef L_wmemcpy
 #define L_memcpy
@@ -255,7 +543,7 @@ Wchar *Wstrncat(Wchar * __restrict s1, register const Wchar * __restrict s2,
 #ifdef L_memcmp
 
 #ifndef L_wmemcmp
-weak_alias(memcmp,bcmp)
+weak_alias(memcmp,bcmp);
 #endif
 
 int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n)
@@ -418,7 +706,7 @@ Wvoid *Wmemchr(const Wvoid *s, Wint c, size_t n)
 #ifdef L_strchr
 
 #ifndef L_wcschr
-weak_alias(strchr,index)
+weak_alias(strchr,index);
 #endif
 
 Wchar *Wstrchr(register const Wchar *s, Wint c)
@@ -492,7 +780,7 @@ Wchar *Wstrpbrk(const Wchar *s1, const Wchar *s2)
 #ifdef L_strrchr
 
 #ifndef L_wcsrchr
-weak_alias(strrchr,rindex)
+weak_alias(strrchr,rindex);
 #endif
 
 Wchar *Wstrrchr(register const  Wchar *s, Wint c)
@@ -548,7 +836,7 @@ size_t Wstrspn(const Wchar *s1, const Wchar *s2)
 /* NOTE: This is the simple-minded O(len(s1) * len(s2)) worst-case approach. */
 
 #ifdef L_wcsstr
-weak_alias(wcsstr,wcswcs)
+weak_alias(wcsstr,wcswcs);
 #endif
 
 Wchar *Wstrstr(const Wchar *s1, const Wchar *s2)
@@ -672,11 +960,6 @@ Wvoid *Wmemset(Wvoid *s, Wint c, size_t n)
 }
 #undef np
 
-#endif
-/**********************************************************************/
-#ifdef L_strerror
-#error implement strerror
-/*  char *strerror(int errnum); */
 #endif
 /**********************************************************************/
 #ifdef L_wcslen
@@ -888,10 +1171,92 @@ Wchar *Wstrdup(register const Wchar *s1)
 	return s;
 }
 
+#endif
+/**********************************************************************/
+#ifdef L_strerror
+
+char *strerror(int errnum)
+{
+    static char buf[_SYS_ERRMSG_MAXLEN];
+
+    return (_susv3_strerror_r(errnum, buf, sizeof(buf)) == 0) ? buf : NULL;
+}
+
+#endif
+/**********************************************************************/
+/* SUSv3 functions. */
+/**********************************************************************/
+#ifdef L__susv3_strerror_r
+
+int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen)
+{
+    register char *s;
+    int i, retval;
+    char buf[_SYS_ERRMSG_MAXLEN];
+    static const char unknown[14] = {
+		'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
+    };
+
+    retval = EINVAL;
+
+    if (((unsigned int) errnum) < _SYS_NERR) {
+		/* Trade time for space.  This function should rarely be called
+		 * so rather than keeping an array of pointers for the different
+		 * messages, just run through the buffer until we find the
+		 * correct string. */
+		for (s = (char *) _string_syserrmsgs, i = errnum ; i ; ++s) {
+			if (!*s) {
+				--i;
+			}
+		}
+		if (*s) {		/* Make sure we have an actual message. */
+			retval = 0;
+			goto GOT_MESG;
+		}
+    }
+
+    s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
+    memcpy(s, unknown, sizeof(unknown));
+
+ GOT_MESG:
+    if (!strerrbuf) {		/* SUSv3  */
+		buflen = 0;
+    }
+    i = strlen(s) + 1;
+    if (i > buflen) {
+		i = buflen;
+		retval = ERANGE;
+    }
+
+    if (i) {
+		memcpy(strerrbuf, s, i);
+		strerrbuf[i-1] = 0;	/* In case buf was too small. */
+    }
+
+    if (retval) {
+		__set_errno(retval);
+    }
+
+    return retval;
+}
+
 #endif
 /**********************************************************************/
 /* GNU extension functions. */
 /**********************************************************************/
+#ifdef L__glibc_strerror_r
+
+weak_alias(_glibc_strerror_r,__strerror_r);
+
+char *_glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen)
+{
+    _susv3_strerror_r(errnum, strerrbuf, buflen);
+
+    return strerrbuf;
+}
+
+#endif
+/**********************************************************************/
 #ifdef L_wmempcpy
 #define L_mempcpy
 #define Wmempcpy wmempcpy
@@ -903,7 +1268,7 @@ Wchar *Wstrdup(register const Wchar *s1)
 
 #ifndef L_wmempcpy
 /* uClibc's old string implementation did this to cater to some app. */
-weak_alias(mempcpy,__mempcpy)
+weak_alias(mempcpy,__mempcpy);
 #endif
 
 Wvoid *Wmempcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)

+ 0 - 8
libc/sysdeps/linux/common/bits/uClibc_stdio.h

@@ -467,14 +467,6 @@ typedef enum {
 	__UIM_UPPER = 'A' - 10,
 } __UIM_CASE;
 
-/* WARNING!!! While similar to the glibc strerror_r function, the
- * following function is not the same.  It expects "unknown" error
- * strings will fit in the buffer passed.  Also, the return value
- * may not be == buf, as unknown strings are "right-justified" in
- * the buf due to the way _int10stostr works. */
-
-extern char *_stdio_strerror_r(int err, char *buf, size_t buflen);
-
 /* Write a NULL-terminated list of "char *" args to file descriptor fd.
  * For an example of usage, see __assert.c.
  */