strerror_r: obey POSIX, and match newlib header change

* errno.cc (__xpg_strerror_r): New function.
(strerror_r): Update to copy newlib's fixes.
(strerror): Set errno on failure.
(_sys_errlist): Cause EINVAL failure for reserved values.
* cygwin.din: Export new function.
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Combine
this into minor 236.
This commit is contained in:
Eric Blake 2011-02-10 17:36:51 +00:00
parent 7c10a76dec
commit 3c9abad56b
4 changed files with 68 additions and 31 deletions

View File

@ -1,3 +1,13 @@
2011-02-10 Eric Blake <eblake@redhat.com>
* errno.cc (__xpg_strerror_r): New function.
(strerror_r): Update to copy newlib's fixes.
(strerror): Set errno on failure.
(_sys_errlist): Cause EINVAL failure for reserved values.
* cygwin.din: Export new function.
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Combine
this into minor 236.
2011-02-09 Yaakov Selkowitz <yselkowitz@users.sourceforge.net> 2011-02-09 Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
* cygwin.din (pthread_yield): Export as alias to sched_yield. * cygwin.din (pthread_yield): Export as alias to sched_yield.

View File

@ -1934,6 +1934,7 @@ xdrrec_skiprecord SIGFE
__xdrrec_getrec SIGFE __xdrrec_getrec SIGFE
__xdrrec_setnonblock SIGFE __xdrrec_setnonblock SIGFE
xdrstdio_create SIGFE xdrstdio_create SIGFE
__xpg_strerror_r SIGFE
y0 NOSIGFE y0 NOSIGFE
y0f NOSIGFE y0f NOSIGFE
y1 NOSIGFE y1 NOSIGFE

View File

@ -199,9 +199,9 @@ const char *_sys_errlist[] NO_COPY_INIT =
/* EL2HLT 44 */ "Level 2 halted", /* EL2HLT 44 */ "Level 2 halted",
/* EDEADLK 45 */ "Resource deadlock avoided", /* EDEADLK 45 */ "Resource deadlock avoided",
/* ENOLCK 46 */ "No locks available", /* ENOLCK 46 */ "No locks available",
"error 47", NULL,
"error 48", NULL,
"error 49", NULL,
/* EBADE 50 */ "Invalid exchange", /* EBADE 50 */ "Invalid exchange",
/* EBADR 51 */ "Invalid request descriptor", /* EBADR 51 */ "Invalid request descriptor",
/* EXFULL 52 */ "Exchange full", /* EXFULL 52 */ "Exchange full",
@ -210,8 +210,8 @@ const char *_sys_errlist[] NO_COPY_INIT =
/* EBADSLT 55 */ "Invalid slot", /* EBADSLT 55 */ "Invalid slot",
/* EDEADLOCK 56 */ "File locking deadlock error", /* EDEADLOCK 56 */ "File locking deadlock error",
/* EBFONT 57 */ "Bad font file format", /* EBFONT 57 */ "Bad font file format",
"error 58", NULL,
"error 59", NULL,
/* ENOSTR 60 */ "Device not a stream", /* ENOSTR 60 */ "Device not a stream",
/* ENODATA 61 */ "No data available", /* ENODATA 61 */ "No data available",
/* ETIME 62 */ "Timer expired", /* ETIME 62 */ "Timer expired",
@ -224,13 +224,13 @@ const char *_sys_errlist[] NO_COPY_INIT =
/* ESRMNT 69 */ "Srmount error", /* ESRMNT 69 */ "Srmount error",
/* ECOMM 70 */ "Communication error on send", /* ECOMM 70 */ "Communication error on send",
/* EPROTO 71 */ "Protocol error", /* EPROTO 71 */ "Protocol error",
"error 72", NULL,
"error 73", NULL,
/* EMULTIHOP 74 */ "Multihop attempted", /* EMULTIHOP 74 */ "Multihop attempted",
/* ELBIN 75 */ "Inode is remote (not really error)", /* ELBIN 75 */ "Inode is remote (not really error)",
/* EDOTDOT 76 */ "RFS specific error", /* EDOTDOT 76 */ "RFS specific error",
/* EBADMSG 77 */ "Bad message", /* EBADMSG 77 */ "Bad message",
"error 78", NULL,
/* EFTYPE 79 */ "Inappropriate file type or format", /* EFTYPE 79 */ "Inappropriate file type or format",
/* ENOTUNIQ 80 */ "Name not unique on network", /* ENOTUNIQ 80 */ "Name not unique on network",
/* EBADFD 81 */ "File descriptor in bad state", /* EBADFD 81 */ "File descriptor in bad state",
@ -245,17 +245,17 @@ const char *_sys_errlist[] NO_COPY_INIT =
/* ENOTEMPTY 90 */ "Directory not empty", /* ENOTEMPTY 90 */ "Directory not empty",
/* ENAMETOOLONG 91 */ "File name too long", /* ENAMETOOLONG 91 */ "File name too long",
/* ELOOP 92 */ "Too many levels of symbolic links", /* ELOOP 92 */ "Too many levels of symbolic links",
"error 93", NULL,
"error 94", NULL,
/* EOPNOTSUPP 95 */ "Operation not supported", /* EOPNOTSUPP 95 */ "Operation not supported",
/* EPFNOSUPPORT 96 */ "Protocol family not supported", /* EPFNOSUPPORT 96 */ "Protocol family not supported",
"error 97", NULL,
"error 98", NULL,
"error 99", NULL,
"error 100", NULL,
"error 101", NULL,
"error 102", NULL,
"error 103", NULL,
/* ECONNRESET 104 */ "Connection reset by peer", /* ECONNRESET 104 */ "Connection reset by peer",
/* ENOBUFS 105 */ "No buffer space available", /* ENOBUFS 105 */ "No buffer space available",
/* EAFNOSUPPORT 106 */ "Address family not supported by protocol", /* EAFNOSUPPORT 106 */ "Address family not supported by protocol",
@ -357,27 +357,53 @@ strerror_worker (int errnum)
return res; return res;
} }
/* strerror: convert from errno values to error strings */ /* strerror: convert from errno values to error strings. Newlib's
strerror_r returns "" for unknown values, so we override it to
provide a nicer thread-safe result string and set errno. */
extern "C" char * extern "C" char *
strerror (int errnum) strerror (int errnum)
{ {
char *errstr = strerror_worker (errnum); char *errstr = strerror_worker (errnum);
if (!errstr) if (!errstr)
__small_sprintf (errstr = _my_tls.locals.strerror_buf, "Unknown error %u", {
(unsigned) errnum); __small_sprintf (errstr = _my_tls.locals.strerror_buf, "Unknown error %u",
(unsigned) errnum);
errno = _impure_ptr->_errno = EINVAL;
}
return errstr; return errstr;
} }
#if 0 /* Newlib's <string.h> provides declarations for two strerror_r
extern "C" int variants, according to preprocessor feature macros. However, it
returns "" instead of "Unknown error ...", so we override both
versions. */
extern "C" char *
strerror_r (int errnum, char *buf, size_t n) strerror_r (int errnum, char *buf, size_t n)
{ {
char *errstr = strerror_worker (errnum); char *error = strerror (errnum);
if (!errstr) if (strlen (error) >= n)
return EINVAL; return error;
if (strlen (errstr) >= n) return strcpy (buf, error);
return ERANGE; }
strcpy (buf, errstr);
return 0; extern "C" int
__xpg_strerror_r (int errnum, char *buf, size_t n)
{
if (!n)
return ERANGE;
int result = 0;
char *error = strerror_worker (errnum);
{
__small_sprintf (error = _my_tls.locals.strerror_buf, "Unknown error %u",
(unsigned) errnum);
result = EINVAL;
}
if (strlen (error) >= n)
{
memcpy (buf, error, n - 1);
buf[n - 1] = '\0';
return ERANGE;
}
strcpy (buf, error);
return result;
} }
#endif

View File

@ -399,7 +399,7 @@ details. */
233: Add TIOCGPGRP, TIOCSPGRP. Export llround, llroundf. 233: Add TIOCGPGRP, TIOCSPGRP. Export llround, llroundf.
234: Export program_invocation_name, program_invocation_short_name. 234: Export program_invocation_name, program_invocation_short_name.
235: Export madvise. 235: Export madvise.
236: Export pthread_yield. 236: Export pthread_yield, __xpg_strerror_r.
*/ */
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */